Tuesday, April 8, 2014

Deserialize an anonymous type using SimpleJson

  1. var json = "{\"name\": \"Joe\"," +
  2. "\"age\": 25," +
  3. "\"address\": {\"city\": \"Paris\"}," +
  4. "\"emails\": [\"joe@home.com\", \"joe@work.com\"]," +
  5. "\"phones\": [{\"type\": \"Mobile\", \"number\": \"555 1234\"}]}";
  6. var prototype = new
  7. {
  8. name = default(string),
  9. age = default(int),
  10. address = new {city = default(string)},
  11. emails = new string[0],
  12. phones = new[] {new {type = default(string), number = default(string)}}
  13. };
  14. var result = SimpleJsonExt.DeserializeAnonymousObject(json, prototype);
  15.  
  16. using CacheEntry = KeyValuePair<ParameterInfo[], ReflectionUtils.ConstructorDelegate>;
  17. public static class SimpleJsonExt
  18. {
  19. public static T DeserializeAnonymousObject<T>(string json, T prototype)
  20. {
  21. return SimpleJson.SimpleJson.DeserializeObject<T>(json, new Strategy());
  22. }
  23. private class Strategy : PocoJsonSerializerStrategy
  24. {
  25. private readonly IDictionary<Type, CacheEntry> _ctorCache =
  26. new ReflectionUtils.ThreadSafeDictionary<Type, CacheEntry>(CreateConstructorDelegate);
  27. private static CacheEntry CreateConstructorDelegate(Type key)
  28. {
  29. var ctors = key.GetConstructors();
  30. if (ctors.Length == 1)
  31. {
  32. var ctor = ctors[0];
  33. var parms = ctor.GetParameters();
  34. if (parms.Length > 0)
  35. {
  36. return new CacheEntry(parms, ReflectionUtils.GetContructor(ctor));
  37. }
  38. }
  39. return default(CacheEntry);
  40. }
  41. public override object DeserializeObject(object value, Type type)
  42. {
  43. var dict = value as IDictionary<string, object>;
  44. if (dict != null)
  45. {
  46. var ctor = _ctorCache[type];
  47. if (ctor.Key != null)
  48. {
  49. return ctor.Value(ctor.Key
  50. .Select(param => DeserializeObject(
  51. dict.TryGetValue(param.Name, out value) ? value : null,
  52. param.ParameterType))
  53. .ToArray());
  54. }
  55. }
  56. return base.DeserializeObject(value, type);
  57. }
  58. }
  59. }
SimpleJson

No comments: