Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • jake williamson 207 posts 872 karma points
    Apr 16, 2015 @ 18:41
    jake williamson
    0

    creating a ditto converter for nuPickers 'SqlDropDownPicker'

    chaps,

    we've just stumbled upon the excellent nuPickers (part of uComponents) and their 'SqlDropDownPicker' fits a problem we've been trying to solve perfectly:

    https://github.com/uComponents/nuPickers/wiki/Data-Source-Sql

    everything is working in terms of umbraco and we've got it returning the data as json which currently looks like this:

    {[{"key":"Spain","label":"Spain (5)"}]}
    

    the problem is when we try to deserialize the json in our converter to get the key, it fails:

    var model = JsonConvert.DeserializeObject<NuPickersSqlDropDownPicker>(value.ToString());
    
    public class NuPickersSqlDropDownPicker
    {
        public String Key { get; set; }
        public String Label { get; set; }
    }
    

    the error is:

    Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Site.Services.Converters.NuPickersSqlDropDownPickerConverter+NuPickersSqlDropDownPicker' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
    

    sure i'm missing something really obvious here (it's been a week...) but is the json actually valid?! i've run it through http://jsonlint.com/ and it's bitching about the opening/closing square brackets...

    has anyone already created a converter for the 'SqlDropDownPicker' and hit this already?

    any suggestions would be grand ;)

    cheers,

    jake

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Apr 16, 2015 @ 18:47
    Lee Kelleher
    0

    Hi Jake,

    In your code example, what type of object is value? As the error is suggesting that it is already a NuPickersSqlDropDownPicker?

    Thanks,
    - Lee

  • Hendy Racher 863 posts 3849 karma points MVP 2x admin c-trib
    Apr 16, 2015 @ 19:46
    Hendy Racher
    0

    Hi Jake,

    Is your saved value:

    {[{"key":"Spain","label":"Spain (5)"}]}

    or

    [{"key":"Spain","label":"Spain (5)"}]

    I think nuPickers when set to Json, will by default, save an array of objects. (the second one), in which case the following should work:

    var model = JsonConvert.DeserializeObject<IEnumerable<NuPickersSqlDropDownPicker>(value.ToString()).FirstOrDefault()

    HTH,

    Hendy


  • jake williamson 207 posts 872 karma points
    Apr 17, 2015 @ 10:20
    jake williamson
    0

    hi,

    thank you for the replies chaps ;)

    sorry, probably should've posted the complete converter:

    using System;
    using System.ComponentModel;
    using Newtonsoft.Json;
    
    namespace Site.Services.Converters
    {
        public class NuPickersSqlDropDownPickerConverter : TypeConverter
        {
            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                return sourceType == typeof(Newtonsoft.Json.Linq.JObject) || base.CanConvertFrom(context, sourceType);
            }
    
            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if ((value == null) || ((String.IsNullOrEmpty(value.ToString())))) return null;
    
                var model = JsonConvert.DeserializeObject<NuPickersSqlDropDownPicker>(value.ToString());
    
                return model == null ? null : model.Key;
            }
    
            public class NuPickersSqlDropDownPicker
            {
                public String Key { get; set; }
                public String Label { get; set; }
            }
        }
    }
    

    the 'value' is coming from umbraco via the model e.g.

    [TypeConverter(typeof(NuPickersSqlDropDownPickerConverter))]
    [UmbracoProperty("speciaOffersCountry")]
    public string Country { get; set; }
    

    hendy, that seems to be the go i.e. the json being returned is an array of objects - which seems odd as the drop down would only have one selected value?

    i've tried the code you've posted but it wasn't happy on 'DeserializeObject' to an 'IEnumerable' so i tried this:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using Newtonsoft.Json;
    
    namespace Site.Services.Converters
    {
        public class NuPickersSqlDropDownPickerConverter : TypeConverter
        {
            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                return sourceType == typeof(Newtonsoft.Json.Linq.JObject) || base.CanConvertFrom(context, sourceType);
            }
    
            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if ((value == null) || ((String.IsNullOrEmpty(value.ToString())))) return null;
    
                var model = JsonConvert.DeserializeObject<Objects>(value.ToString());
    
                return model == null ? null : model.Values.First().Key;
            }
    
            public class Objects
            {
                public IEnumerable<NuPickersSqlDropDownPicker> Values { get; set; }
            }
    
            public class NuPickersSqlDropDownPicker
            {
                public String Key { get; set; }
                public String Label { get; set; }
            }
        }
    }
    

    but no dice, i still get the deserialize error!

    it's weird, we've written a bunch of ditto converters that handle json strings and this is the 1st that's thrown a curve ball!

    it must either be the json itself or the class we're trying to deserialize it to?

    cheers,

    jake

  • Hendy Racher 863 posts 3849 karma points MVP 2x admin c-trib
    Apr 17, 2015 @ 10:36
    Hendy Racher
    0

    Hi Jake,

    I wonder if it's the Property Value Converter built into nuPickers ? can you confirm that the value parameter is a string of Json ? I think it could be a Picker object, in which case you can do a ToString() on it to get the raw saved value.

    Hendy

  • jake williamson 207 posts 872 karma points
    Apr 17, 2015 @ 10:37
    jake williamson
    101

    cracked it!

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using Newtonsoft.Json;
    
    namespace Site.Services.Converters
    {
        public class NuPickersSqlDropDownPickerConverter : TypeConverter
        {
            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                return sourceType == typeof(Newtonsoft.Json.Linq.JObject) || base.CanConvertFrom(context, sourceType);
            }
    
            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if ((value == null) || ((String.IsNullOrEmpty(value.ToString())))) return null;
    
                var model = JsonConvert.DeserializeObject<IEnumerable<NuPickersSqlDropDownPicker>>(value.ToString());
    
                return model == null ? null : model.First().Key;
            }
    
            public class NuPickersSqlDropDownPicker
            {
                public String Key { get; set; }
                public String Label { get; set; }
            }
        }
    }
    

    hendy, you totally had it but a typo was throwing me out ;)

    phew... got there in the end ;)

    the only thing i still don't get is why the json is returning an array when the drop down only has one selected value... but hey, that's a question for another time!

    cheers,

    jake

  • Hendy Racher 863 posts 3849 karma points MVP 2x admin c-trib
    Apr 17, 2015 @ 10:46
    Hendy Racher
    0

    Hi Jake, it stores a single item within an array, as all the property editors share the same save code. The dropdown, radiobutton and list pickers restricted to a max of one item could potentially be changed to store a single object.

  • jake williamson 207 posts 872 karma points
    Apr 17, 2015 @ 11:31
    jake williamson
    0

    hi hendy, thanks for clarifying that, makes sense ;)

    one small update: if no value is selected in the drop down, the value returned isn't json... so i've added 'value.ToString() == "nuPickers.Picker"' to the opening if statement to skip over the conversion if no value exists.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using Newtonsoft.Json;
    
    namespace Site.Services.Converters
    {
        public class NuPickersSqlDropDownPickerConverter : TypeConverter
        {
            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                return sourceType == typeof(Newtonsoft.Json.Linq.JObject) || base.CanConvertFrom(context, sourceType);
            }
    
            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if ((value == null) || ((String.IsNullOrEmpty(value.ToString()))) || (value.ToString() == "nuPickers.Picker")) return null;
    
                var model = JsonConvert.DeserializeObject<IEnumerable<NuPickersSqlDropDownPicker>>(value.ToString());
    
                return model == null ? null : model.First().Key;
            }
    
            public class NuPickersSqlDropDownPicker
            {
                public String Key { get; set; }
                public String Label { get; set; }
            }
        }
    }
    

    cheers,

    jake

Please Sign in or register to post replies

Write your reply to:

Draft