PageRenderTime 49ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/FbAds/test/packages/json_mapper/json_mapper.dart

https://gitlab.com/domosi/fb-ads
Dart | 181 lines | 112 code | 22 blank | 47 comment | 48 complexity | 71cd6d0ecfb82a9fc1a4356c53498651 MD5 | raw file
  1. library json_mapper;
  2. import 'dart:mirrors' as mirrors;
  3. import 'dart:convert' as convert;
  4. const _EMPTY_SYMBOL = const Symbol('');
  5. /**
  6. * Helper class to deserialize generic types. Due to limitations of
  7. * the Dart language, we cannot have an expresion like so:
  8. *
  9. * import 'package:json_mapper/json_mapper.dart' as jmap;
  10. * int main() {
  11. * List<Contact> contacts = jmap.deserialize(jsonString, <Contact>[].runtimeType);
  12. * }
  13. *
  14. * We can use the helper to help us out:
  15. *
  16. * jmap.deserialize(jsonString, TypeOf<List<ContactType>>.type);
  17. */
  18. class TypeOf<T> {
  19. Type get type => T;
  20. const TypeOf();
  21. }
  22. /**
  23. * Serializes the provided [obj] into a valid JSON [String].
  24. * [obj] The object to be serialized.
  25. *
  26. * Can accept a list, map, or any instance of a class. Will throw
  27. * a [ArgumentError] if the input is a scalar value, as it will not
  28. * produce valid JSON.
  29. */
  30. String serialize(Object obj) {
  31. if (obj == null) {
  32. return null;
  33. }
  34. if (_isPrimitiveType(obj)) { // entry value can only be object, map, or list.
  35. throw new ArgumentError('Cannot serialize a scalar value into a JSON representation.');
  36. }
  37. return convert.JSON.encode(_serializeObject(obj));
  38. }
  39. /**
  40. * Recursively serializes the provided [obj].
  41. * For internal use only.
  42. */
  43. dynamic _serializeObject(Object obj) {
  44. if (obj == null) {
  45. return null;
  46. }
  47. if (_isPrimitiveType(obj)) {
  48. return obj;
  49. }
  50. if (obj is List) {
  51. List<Object> list = new List<Object>();
  52. for (var e in obj) {
  53. list.add(_serializeObject(e));
  54. }
  55. return list;
  56. }
  57. Map<String, Object> data = new Map<String, Object>();
  58. if (obj is Map) {
  59. // what if key is not string?
  60. for (var k in obj.keys) {
  61. data[k] = _serializeObject(obj[k]);
  62. }
  63. return data;
  64. }
  65. // serializes object fields and getters.
  66. mirrors.InstanceMirror im = mirrors.reflect(obj);
  67. mirrors.ClassMirror cm = im.type;
  68. while (cm.superclass != null) {
  69. cm.declarations.forEach((Symbol sym, dynamic dec) {
  70. if (dec is mirrors.VariableMirror) {
  71. if (_isSerializableVariable(dec)) {
  72. data[mirrors.MirrorSystem.getName(sym)] = _serializeObject(im.getField(dec.simpleName).reflectee);
  73. }
  74. } else if (dec is mirrors.MethodMirror) {
  75. if (_hasGetter(cm, dec) && _isSerializableGetter(dec)) {
  76. data[mirrors.MirrorSystem.getName(sym)] = _serializeObject(im.getField(dec.simpleName).reflectee);
  77. }
  78. }
  79. });
  80. cm = cm.superclass;
  81. }
  82. return data;
  83. }
  84. /**
  85. * Deserializes a JSON [String] and maps it to the provided [type].
  86. * Returns the an Object of type passed to [type]
  87. */
  88. dynamic deserialize(String json, Type type) {
  89. if (json == null) {
  90. return null;
  91. }
  92. return _deserializeObject(convert.JSON.decode(json), type);
  93. }
  94. /**
  95. * Recursive function for mapping a [json] to the provided [type]
  96. */
  97. dynamic _deserializeObject(dynamic json, Type type) {
  98. if (json == null) {
  99. return null;
  100. }
  101. if (_isPrimitiveType(json)) {
  102. return json;
  103. }
  104. mirrors.ClassMirror cm = mirrors.reflectClass(type);
  105. mirrors.InstanceMirror instance = cm.newInstance(_EMPTY_SYMBOL, []);
  106. var ref = instance.reflectee;
  107. if (ref is List) {
  108. Type valType = mirrors.reflectType(type).typeArguments.single.reflectedType;
  109. for (var item in json) {
  110. ref.add(_deserializeObject(item, valType));
  111. }
  112. } else if (ref is Map) {
  113. Type valType = mirrors.reflectType(type).typeArguments.last.reflectedType;
  114. for (var key in json.keys) {
  115. ref[key] = _deserializeObject(json[key], valType);
  116. }
  117. } else {
  118. for (var key in json.keys) {
  119. Symbol sym = new Symbol(key);
  120. var dec = cm.instanceMembers[sym];
  121. if (dec != null) {
  122. if (dec is mirrors.VariableMirror && _isSerializableVariable(dec)) {
  123. instance.setField(sym, _deserializeObject(json[key], dec.type.reflectedType));
  124. } else if (dec is mirrors.MethodMirror) {
  125. if (_hasGetter(cm, dec) && _isSerializableGetter(dec)) {
  126. instance.setField(sym, _deserializeObject(json[key], dec.returnType.reflectedType));
  127. }
  128. }
  129. }
  130. }
  131. }
  132. return ref;
  133. }
  134. /**
  135. * Returns true if [obj] is a [num], [String], or [bool].
  136. */
  137. bool _isPrimitiveType(Object obj) {
  138. return obj is num || obj is String || obj is bool;
  139. }
  140. /**
  141. * Returns true if the variable is a public instance variable.
  142. */
  143. bool _isSerializableVariable(mirrors.VariableMirror vm) {
  144. return !vm.isStatic && !vm.isFinal && !vm.isPrivate;
  145. }
  146. /**
  147. * Returns true if the method is a public instance getter.
  148. */
  149. bool _isSerializableGetter(mirrors.MethodMirror mm) {
  150. return mm.isGetter && !mm.isStatic && !mm.isPrivate;
  151. }
  152. /**
  153. * Checks if the following [mm] getter method has a corresponding setter method.
  154. * Returns `true` if one is found, false otherwise.
  155. */
  156. bool _hasGetter(mirrors.ClassMirror cm, mirrors.MethodMirror mm) {
  157. var setterDec = cm.instanceMembers[new Symbol(mirrors.MirrorSystem.getName(mm.simpleName) + '=')];
  158. return setterDec != null && !setterDec.isPrivate && !setterDec.isStatic && setterDec.isSetter;
  159. }