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:
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?
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?
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.
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!
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.
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; }
}
}
}
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:
the problem is when we try to deserialize the json in our converter to get the key, it fails:
the error is:
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
Hi Jake,
In your code example, what type of object is
value
? As the error is suggesting that it is already aNuPickersSqlDropDownPicker
?Thanks,
- Lee
Hi Jake,
Is your saved value:
or
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:
HTH,
Hendy
hi,
thank you for the replies chaps ;)
sorry, probably should've posted the complete converter:
the 'value' is coming from umbraco via the model e.g.
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:
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
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
cracked it!
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
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.
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.
cheers,
jake
is working on a reply...