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 873 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 4026 posts 15837 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 873 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 873 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 873 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

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies