Reputation:
When I Deserialize this object everything works except for Images? The only way I have figured out how to get the images out is to use the method 'GetImages()'. I would like to not have to use this a method where I return a Dictionary Key results. I've tried structuring the object so many different way, but have yet to successfully find the answer.
Here is the object.
public class Item
{
public int itemId { get; set; }
public double systemSku { get; set; }
public int itemECommerceID { get; set; }
public Dictionary<string, List<Image>> Images { get; set; }
public Category Category { get; set; }
public List<Image> GetImages()
{
return this.Images["Image"];
}
}
Image Class:
public class Image
{
public int imageID { get; set; }
public string description { get; set; }
public string filename { get; set; }
public int ordering { get; set; }
public string publicID { get; set; }
public string baseImageURL { get; set; }
public int itemID { get; set; }
public int itemMatrixID { get; set; }
public string imageUrl
{
get
{
return string.Format("{0}{1}.jpg", baseImageURL, publicID);
}
}
}
Excerpt of serialization code:
var stream = await response.Content.ReadAsStreamAsync();
StreamReader reader = new StreamReader(stream);
JavaScriptSerializer js = new JavaScriptSerializer();
var tmpObj = js.Deserialize<dynamic>(reader.ReadToEnd());
TResult obj = js.Deserialize<TResult>(js.Serialize(tmpObj[key]));
Upvotes: 0
Views: 763
Reputation: 12847
JSON serialization does not on it's own handle complex typed (non string, int etc...) dictionaries, you would have to create your own Dictionary Serialization mechanism or do what you are doing via List<>
.
I ran across this same issue when trying to make a more efficient serializer/deserializer for WCF, while JSON will be more compact it is lacking in complicated object graphs.
Upvotes: 1
Reputation: 116526
Purely as a matter of serialization/deserialization, I was able to serialize and deserialize your Dictionary<string, List<Image>>
by using the following JavaScriptConverter
:
public class JavaScriptImageConverter : JavaScriptConverter
{
readonly List<Type> Types = new List<Type>();
const string base64key = "Base64Image";
public JavaScriptImageConverter() : base()
{
Types.Add(typeof(Bitmap)); // Add additional types if required?
Types.Add(typeof(Image));
}
static string ToBase64String(System.Drawing.Image imageIn)
{
if (imageIn == null)
return null;
ImageConverter converter = new ImageConverter();
return Convert.ToBase64String((byte[])converter.ConvertTo(imageIn, typeof(byte[])));
}
public static Image FromBase64String(string imageString)
{
if (string.IsNullOrEmpty(imageString))
return null;
ImageConverter converter = new ImageConverter();
return (Image)converter.ConvertFrom(Convert.FromBase64String(imageString));
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (!typeof(Image).IsAssignableFrom(type))
return null;
object obj;
if (!dictionary.TryGetValue(base64key, out obj))
return null;
var str = obj as string;
if (str == null)
return null;
return FromBase64String(str);
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var image = (Image)obj;
var serialized = new Dictionary<string, object>();
serialized[base64key] = ToBase64String(image);
return serialized;
}
public override IEnumerable<Type> SupportedTypes
{
get {
return Types;
}
}
}
And then use it like:
var js = new JavaScriptSerializer();
js.RegisterConverters(new JavaScriptConverter[] { new JavaScriptImageConverter() });
js.MaxJsonLength = int.MaxValue / 8; // Because my test string turned out to be VERY LONG.
var imageJson = js.Serialize(item);
using (var itemBack = js.Deserialize<Item>(imageJson))
{
var ok1 = itemBack.Images.SelectMany(p => p.Value).Select(i => i.Width).SequenceEqual(item.Images.SelectMany(p => p.Value).Select(i => i.Width));
Debug.Assert(ok1); // No assert.
var ok2 = itemBack.Images.SelectMany(p => p.Value).Select(i => i.Height).SequenceEqual(item.Images.SelectMany(p => p.Value).Select(i => i.Height));
Debug.Assert(ok2); // No assert.
}
Note I got much better serialization/deserialization performance using a base64 string than by using a byte []
array directly.
(Maybe this way of serializing images is too nonstandard for your tastes?)
Upvotes: 1