MTLJSONAdapter.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. //
  2. // MTLJSONAdapter.h
  3. // Mantle
  4. //
  5. // Created by Justin Spahr-Summers on 2013-02-12.
  6. // Copyright (c) 2013 GitHub. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. @protocol MTLModel;
  10. @protocol MTLTransformerErrorHandling;
  11. /// A MTLModel object that supports being parsed from and serialized to JSON.
  12. @protocol MTLJSONSerializing <MTLModel>
  13. @required
  14. /// Specifies how to map property keys to different key paths in JSON.
  15. ///
  16. /// Subclasses overriding this method should combine their values with those of
  17. /// `super`.
  18. ///
  19. /// Values in the dictionary can either be key paths in the JSON representation
  20. /// of the receiver or an array of such key paths. If an array is used, the
  21. /// deserialized value will be a dictionary containing all of the keys in the
  22. /// array.
  23. ///
  24. /// Any keys omitted will not participate in JSON serialization.
  25. ///
  26. /// Examples
  27. ///
  28. /// + (NSDictionary *)JSONKeyPathsByPropertyKey {
  29. /// return @{
  30. /// @"name": @"POI.name",
  31. /// @"point": @[ @"latitude", @"longitude" ],
  32. /// @"starred": @"starred"
  33. /// };
  34. /// }
  35. ///
  36. /// This will map the `starred` property to `JSONDictionary[@"starred"]`, `name`
  37. /// to `JSONDictionary[@"POI"][@"name"]` and `point` to a dictionary equivalent
  38. /// to:
  39. ///
  40. /// @{
  41. /// @"latitude": JSONDictionary[@"latitude"],
  42. /// @"longitude": JSONDictionary[@"longitude"]
  43. /// }
  44. ///
  45. /// Returns a dictionary mapping property keys to one or multiple JSON key paths
  46. /// (as strings or arrays of strings).
  47. + (NSDictionary *)JSONKeyPathsByPropertyKey;
  48. @optional
  49. /// Specifies how to convert a JSON value to the given property key. If
  50. /// reversible, the transformer will also be used to convert the property value
  51. /// back to JSON.
  52. ///
  53. /// If the receiver implements a `+<key>JSONTransformer` method, MTLJSONAdapter
  54. /// will use the result of that method instead.
  55. ///
  56. /// Returns a value transformer, or nil if no transformation should be performed.
  57. + (NSValueTransformer *)JSONTransformerForKey:(NSString *)key;
  58. /// Overridden to parse the receiver as a different class, based on information
  59. /// in the provided dictionary.
  60. ///
  61. /// This is mostly useful for class clusters, where the abstract base class would
  62. /// be passed into -[MTLJSONAdapter initWithJSONDictionary:modelClass:], but
  63. /// a subclass should be instantiated instead.
  64. ///
  65. /// JSONDictionary - The JSON dictionary that will be parsed.
  66. ///
  67. /// Returns the class that should be parsed (which may be the receiver), or nil
  68. /// to abort parsing (e.g., if the data is invalid).
  69. + (Class)classForParsingJSONDictionary:(NSDictionary *)JSONDictionary;
  70. @end
  71. /// The domain for errors originating from MTLJSONAdapter.
  72. extern NSString * const MTLJSONAdapterErrorDomain;
  73. /// +classForParsingJSONDictionary: returned nil for the given dictionary.
  74. extern const NSInteger MTLJSONAdapterErrorNoClassFound;
  75. /// The provided JSONDictionary is not valid.
  76. extern const NSInteger MTLJSONAdapterErrorInvalidJSONDictionary;
  77. /// The model's implementation of +JSONKeyPathsByPropertyKey included a key which
  78. /// does not actually exist in +propertyKeys.
  79. extern const NSInteger MTLJSONAdapterErrorInvalidJSONMapping;
  80. /// Converts a MTLModel object to and from a JSON dictionary.
  81. @interface MTLJSONAdapter : NSObject
  82. /// Attempts to parse a JSON dictionary into a model object.
  83. ///
  84. /// modelClass - The MTLModel subclass to attempt to parse from the JSON.
  85. /// This class must conform to <MTLJSONSerializing>. This
  86. /// argument must not be nil.
  87. /// JSONDictionary - A dictionary representing JSON data. This should match the
  88. /// format returned by NSJSONSerialization. If this argument is
  89. /// nil, the method returns nil.
  90. /// error - If not NULL, this may be set to an error that occurs during
  91. /// parsing or initializing an instance of `modelClass`.
  92. ///
  93. /// Returns an instance of `modelClass` upon success, or nil if a parsing error
  94. /// occurred.
  95. + (id)modelOfClass:(Class)modelClass fromJSONDictionary:(NSDictionary *)JSONDictionary error:(NSError **)error;
  96. /// Attempts to parse an array of JSON dictionary objects into a model objects
  97. /// of a specific class.
  98. ///
  99. /// modelClass - The MTLModel subclass to attempt to parse from the JSON. This
  100. /// class must conform to <MTLJSONSerializing>. This argument must
  101. /// not be nil.
  102. /// JSONArray - A array of dictionaries representing JSON data. This should
  103. /// match the format returned by NSJSONSerialization. If this
  104. /// argument is nil, the method returns nil.
  105. /// error - If not NULL, this may be set to an error that occurs during
  106. /// parsing or initializing an any of the instances of
  107. /// `modelClass`.
  108. ///
  109. /// Returns an array of `modelClass` instances upon success, or nil if a parsing
  110. /// error occurred.
  111. + (NSArray *)modelsOfClass:(Class)modelClass fromJSONArray:(NSArray *)JSONArray error:(NSError **)error;
  112. /// Converts a model into a JSON representation.
  113. ///
  114. /// model - The model to use for JSON serialization. This argument must not be
  115. /// nil.
  116. /// error - If not NULL, this may be set to an error that occurs during
  117. /// serializing.
  118. ///
  119. /// Returns a JSON dictionary, or nil if a serialization error occurred.
  120. + (NSDictionary *)JSONDictionaryFromModel:(id<MTLJSONSerializing>)model error:(NSError **)error;
  121. /// Converts a array of models into a JSON representation.
  122. ///
  123. /// models - The array of models to use for JSON serialization. This argument
  124. /// must not be nil.
  125. /// error - If not NULL, this may be set to an error that occurs during
  126. /// serializing.
  127. ///
  128. /// Returns a JSON array, or nil if a serialization error occurred for any
  129. /// model.
  130. + (NSArray *)JSONArrayFromModels:(NSArray *)models error:(NSError **)error;
  131. /// Initializes the receiver with a given model class.
  132. ///
  133. /// modelClass - The MTLModel subclass to attempt to parse from the JSON and
  134. /// back. This class must conform to <MTLJSONSerializing>. This
  135. /// argument must not be nil.
  136. ///
  137. /// Returns an initialized adapter.
  138. - (id)initWithModelClass:(Class)modelClass;
  139. /// Deserializes a model from a JSON dictionary.
  140. ///
  141. /// The adapter will call -validate: on the model and consider it an error if the
  142. /// validation fails.
  143. ///
  144. /// JSONDictionary - A dictionary representing JSON data. This should match the
  145. /// format returned by NSJSONSerialization. This argument must
  146. /// not be nil.
  147. /// error - If not NULL, this may be set to an error that occurs during
  148. /// deserializing or validation.
  149. ///
  150. /// Returns a model object, or nil if a deserialization error occurred or the
  151. /// model did not validate successfully.
  152. - (id)modelFromJSONDictionary:(NSDictionary *)JSONDictionary error:(NSError **)error;
  153. /// Serializes a model into JSON.
  154. ///
  155. /// model - The model to use for JSON serialization. This argument must not be
  156. /// nil.
  157. /// error - If not NULL, this may be set to an error that occurs during
  158. /// serializing.
  159. ///
  160. /// Returns a model object, or nil if a serialization error occurred.
  161. - (NSDictionary *)JSONDictionaryFromModel:(id<MTLJSONSerializing>)model error:(NSError **)error;
  162. /// Filters the property keys used to serialize a given model.
  163. ///
  164. /// propertyKeys - The property keys for which `model` provides a mapping.
  165. /// model - The model being serialized.
  166. ///
  167. /// Subclasses may override this method to determine which property keys should
  168. /// be used when serializing `model`. For instance, this method can be used to
  169. /// create more efficient updates of server-side resources.
  170. ///
  171. /// The default implementation simply returns `propertyKeys`.
  172. ///
  173. /// Returns a subset of propertyKeys that should be serialized for a given
  174. /// model.
  175. - (NSSet *)serializablePropertyKeys:(NSSet *)propertyKeys forModel:(id<MTLJSONSerializing>)model;
  176. /// An optional value transformer that should be used for properties of the given
  177. /// class.
  178. ///
  179. /// A value transformer returned by the model's +JSONTransformerForKey: method
  180. /// is given precedence over the one returned by this method.
  181. ///
  182. /// The default implementation invokes `+<class>JSONTransformer` on the
  183. /// receiver if it's implemented. It supports NSURL conversion through
  184. /// +NSURLJSONTransformer.
  185. ///
  186. /// modelClass - The class of the property to serialize. This property must not be
  187. /// nil.
  188. ///
  189. /// Returns a value transformer or nil if no transformation should be used.
  190. + (NSValueTransformer *)transformerForModelPropertiesOfClass:(Class)modelClass;
  191. /// A value transformer that should be used for a properties of the given
  192. /// primitive type.
  193. ///
  194. /// If `objCType` matches @encode(id), the value transformer returned by
  195. /// +transformerForModelPropertiesOfClass: is used instead.
  196. ///
  197. /// The default implementation transforms properties that match @encode(BOOL)
  198. /// using the MTLBooleanValueTransformerName transformer.
  199. ///
  200. /// objCType - The type encoding for the value of this property. This is the type
  201. /// as it would be returned by the @encode() directive.
  202. ///
  203. /// Returns a value transformer or nil if no transformation should be used.
  204. + (NSValueTransformer *)transformerForModelPropertiesOfObjCType:(const char *)objCType;
  205. @end
  206. @interface MTLJSONAdapter (ValueTransformers)
  207. /// Creates a reversible transformer to convert a JSON dictionary into a MTLModel
  208. /// object, and vice-versa.
  209. ///
  210. /// modelClass - The MTLModel subclass to attempt to parse from the JSON. This
  211. /// class must conform to <MTLJSONSerializing>. This argument must
  212. /// not be nil.
  213. ///
  214. /// Returns a reversible transformer which uses the class of the receiver for
  215. /// transforming values back and forth.
  216. + (NSValueTransformer<MTLTransformerErrorHandling> *)dictionaryTransformerWithModelClass:(Class)modelClass;
  217. /// Creates a reversible transformer to convert an array of JSON dictionaries
  218. /// into an array of MTLModel objects, and vice-versa.
  219. ///
  220. /// modelClass - The MTLModel subclass to attempt to parse from each JSON
  221. /// dictionary. This class must conform to <MTLJSONSerializing>.
  222. /// This argument must not be nil.
  223. ///
  224. /// Returns a reversible transformer which uses the class of the receiver for
  225. /// transforming array elements back and forth.
  226. + (NSValueTransformer<MTLTransformerErrorHandling> *)arrayTransformerWithModelClass:(Class)modelClass;
  227. /// This value transformer is used by MTLJSONAdapter to automatically convert
  228. /// NSURL properties to JSON strings and vice versa.
  229. + (NSValueTransformer *)NSURLJSONTransformer;
  230. @end
  231. @class MTLModel;
  232. @interface MTLJSONAdapter (Deprecated)
  233. @property (nonatomic, strong, readonly) id<MTLJSONSerializing> model __attribute__((unavailable("Replaced by -modelFromJSONDictionary:error:")));
  234. + (NSArray *)JSONArrayFromModels:(NSArray *)models __attribute__((deprecated("Replaced by +JSONArrayFromModels:error:")));
  235. + (NSDictionary *)JSONDictionaryFromModel:(MTLModel<MTLJSONSerializing> *)model __attribute__((deprecated("Replaced by +JSONDictionaryFromModel:error:")));
  236. - (NSDictionary *)JSONDictionary __attribute__((unavailable("Replaced by -JSONDictionaryFromModel:error:")));
  237. - (NSString *)JSONKeyPathForPropertyKey:(NSString *)key __attribute__((unavailable("Replaced by -serializablePropertyKeys:forModel:")));
  238. - (id)initWithJSONDictionary:(NSDictionary *)JSONDictionary modelClass:(Class)modelClass error:(NSError **)error __attribute__((unavailable("Replaced by -initWithModelClass:")));
  239. - (id)initWithModel:(id<MTLJSONSerializing>)model __attribute__((unavailable("Replaced by -initWithModelClass:")));
  240. - (NSDictionary *)serializeToJSONDictionary:(NSError **)error __attribute__((unavailable("Replaced by -JSONDictionaryFromModel:error:")));
  241. @end