forked from jsonmodel/jsonmodel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
JSONModel.h
274 lines (239 loc) · 11.5 KB
/
JSONModel.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
//
// JSONModel.h
// JSONModel
//
#import <Foundation/Foundation.h>
#import "JSONModelError.h"
#import "JSONValueTransformer.h"
#import "JSONKeyMapper.h"
/////////////////////////////////////////////////////////////////////////////////////////////
#if TARGET_IPHONE_SIMULATOR
#define JMLog( s, ... ) NSLog( @"[%@:%d] %@", [[NSString stringWithUTF8String:__FILE__] \
lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define JMLog( s, ... )
#endif
/////////////////////////////////////////////////////////////////////////////////////////////
DEPRECATED_ATTRIBUTE
@protocol ConvertOnDemand
@end
DEPRECATED_ATTRIBUTE
@protocol Index
@end
#pragma mark - Property Protocols
/**
* Protocol for defining properties in a JSON Model class that should not be considered at all
* neither while importing nor when exporting JSON.
*
* @property (strong, nonatomic) NSString<Ignore> *propertyName;
*
*/
@protocol Ignore
@end
/**
* Protocol for defining optional properties in a JSON Model class. Use like below to define
* model properties that are not required to have values in the JSON input:
*
* @property (strong, nonatomic) NSString<Optional> *propertyName;
*
*/
@protocol Optional
@end
/**
* Make all objects compatible to avoid compiler warnings
*/
@interface NSObject (JSONModelPropertyCompatibility) <Optional, Ignore>
@end
/////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - JSONModel protocol
/**
* A protocol describing an abstract JSONModel class
* JSONModel conforms to this protocol, so it can use itself abstractly
*/
@protocol AbstractJSONModelProtocol <NSCopying, NSCoding>
@required
/**
* All JSONModel classes should implement initWithDictionary:
*
* For most classes the default initWithDictionary: inherited from JSONModel itself
* should suffice, but developers have the option to also overwrite it if needed.
*
* @param dict a dictionary holding JSON objects, to be imported in the model.
* @param err an error or NULL
*/
- (instancetype)initWithDictionary:(NSDictionary *)dict error:(NSError **)err;
/**
* All JSONModel classes should implement initWithData:error:
*
* For most classes the default initWithData: inherited from JSONModel itself
* should suffice, but developers have the option to also overwrite it if needed.
*
* @param data representing a JSON response (usually fetched from web), to be imported in the model.
* @param error an error or NULL
*/
- (instancetype)initWithData:(NSData *)data error:(NSError **)error;
/**
* All JSONModel classes should be able to export themselves as a dictionary of
* JSON compliant objects.
*
* For most classes the inherited from JSONModel default toDictionary implementation
* should suffice.
*
* @return NSDictionary dictionary of JSON compliant objects
* @exception JSONModelTypeNotAllowedException thrown when one of your model's custom class properties
* does not have matching transformer method in an JSONValueTransformer.
*/
- (NSDictionary *)toDictionary;
/**
* Export a model class to a dictionary, including only given properties
*
* @param propertyNames the properties to export; if nil, all properties exported
* @return NSDictionary dictionary of JSON compliant objects
* @exception JSONModelTypeNotAllowedException thrown when one of your model's custom class properties
* does not have matching transformer method in an JSONValueTransformer.
*/
- (NSDictionary *)toDictionaryWithKeys:(NSArray *)propertyNames;
@end
/////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - JSONModel interface
/**
* The JSONModel is an abstract model class, you should not instantiate it directly,
* as it does not have any properties, and therefore cannot serve as a data model.
* Instead you should subclass it, and define the properties you want your data model
* to have as properties of your own class.
*/
@interface JSONModel : NSObject <AbstractJSONModelProtocol, NSSecureCoding>
// deprecated
+ (NSMutableArray *)arrayOfModelsFromDictionaries:(NSArray *)array DEPRECATED_MSG_ATTRIBUTE("use arrayOfModelsFromDictionaries:error:");
+ (void)setGlobalKeyMapper:(JSONKeyMapper *)globalKeyMapper DEPRECATED_MSG_ATTRIBUTE("override +keyMapper in a base model class instead");
+ (NSString *)protocolForArrayProperty:(NSString *)propertyName DEPRECATED_MSG_ATTRIBUTE("use classForCollectionProperty:");
- (void)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping DEPRECATED_MSG_ATTRIBUTE("use mergeFromDictionary:useKeyMapping:error:");
- (NSString *)indexPropertyName DEPRECATED_ATTRIBUTE;
- (NSComparisonResult)compare:(id)object DEPRECATED_ATTRIBUTE;
/** @name Creating and initializing models */
/**
* Create a new model instance and initialize it with the JSON from a text parameter. The method assumes UTF8 encoded input text.
* @param string JSON text data
* @param err an initialization error or nil
* @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON,
* or a property type in your model is not supported by JSONValueTransformer and its categories
* @see initWithString:usingEncoding:error: for use of custom text encodings
*/
- (instancetype)initWithString:(NSString *)string error:(JSONModelError **)err;
/**
* Create a new model instance and initialize it with the JSON from a text parameter using the given encoding.
* @param string JSON text data
* @param encoding the text encoding to use when parsing the string (see NSStringEncoding)
* @param err an initialization error or nil
* @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON,
* or a property type in your model is not supported by JSONValueTransformer and its categories
*/
- (instancetype)initWithString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(JSONModelError **)err;
/** @name Exporting model contents */
/**
* Export the whole object to a JSON data text string
* @return JSON text describing the data model
*/
- (NSString *)toJSONString;
/**
* Export the whole object to a JSON data text string
* @return JSON text data describing the data model
*/
- (NSData *)toJSONData;
/**
* Export the specified properties of the object to a JSON data text string
* @param propertyNames the properties to export; if nil, all properties exported
* @return JSON text describing the data model
*/
- (NSString *)toJSONStringWithKeys:(NSArray *)propertyNames;
/**
* Export the specified properties of the object to a JSON data text string
* @param propertyNames the properties to export; if nil, all properties exported
* @return JSON text data describing the data model
*/
- (NSData *)toJSONDataWithKeys:(NSArray *)propertyNames;
/** @name Batch methods */
/**
* If you have a list of dictionaries in a JSON feed, you can use this method to create an NSArray
* of model objects. Handy when importing JSON data lists.
* This method will loop over the input list and initialize a data model for every dictionary in the list.
*
* @param array list of dictionaries to be imported as models
* @return list of initialized data model objects
* @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON,
* or a property type in your model is not supported by JSONValueTransformer and its categories
* @exception JSONModelInvalidDataException thrown when the input data does not include all required keys
* @see arrayOfDictionariesFromModels:
*/
+ (NSMutableArray *)arrayOfModelsFromDictionaries:(NSArray *)array error:(NSError **)err;
+ (NSMutableArray *)arrayOfModelsFromData:(NSData *)data error:(NSError **)err;
+ (NSMutableArray *)arrayOfModelsFromString:(NSString *)string error:(NSError **)err;
+ (NSMutableDictionary *)dictionaryOfModelsFromDictionary:(NSDictionary *)dictionary error:(NSError **)err;
+ (NSMutableDictionary *)dictionaryOfModelsFromData:(NSData *)data error:(NSError **)err;
+ (NSMutableDictionary *)dictionaryOfModelsFromString:(NSString *)string error:(NSError **)err;
/**
* If you have an NSArray of data model objects, this method takes it in and outputs a list of the
* matching dictionaries. This method does the opposite of arrayOfObjectsFromDictionaries:
* @param array list of JSONModel objects
* @return a list of NSDictionary objects
* @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON,
* or a property type in your model is not supported by JSONValueTransformer and its categories
* @see arrayOfModelsFromDictionaries:
*/
+ (NSMutableArray *)arrayOfDictionariesFromModels:(NSArray *)array;
+ (NSMutableDictionary *)dictionaryOfDictionariesFromModels:(NSDictionary *)dictionary;
/** @name Validation */
/**
* Overwrite the validate method in your own models if you need to perform some custom validation over the model data.
* This method gets called at the very end of the JSONModel initializer, thus the model is in the state that you would
* get it back when initialized. Check the values of any property that needs to be validated and if any invalid values
* are encountered return NO and set the error parameter to an NSError object. If the model is valid return YES.
*
* NB: Only setting the error parameter is not enough to fail the validation, you also need to return a NO value.
*
* @param error a pointer to an NSError object, to pass back an error if needed
* @return a BOOL result, showing whether the model data validates or not. You can use the convenience method
* [JSONModelError errorModelIsInvalid] to set the NSError param if the data fails your custom validation
*/
- (BOOL)validate:(NSError **)error;
/** @name Key mapping */
/**
* Overwrite in your models if your property names don't match your JSON key names.
* Lookup JSONKeyMapper docs for more details.
*/
+ (JSONKeyMapper *)keyMapper;
/**
* Indicates whether the property with the given name is Optional.
* To have a model with all of its properties being Optional just return YES.
* This method returns by default NO, since the default behaviour is to have all properties required.
* @param propertyName the name of the property
* @return a BOOL result indicating whether the property is optional
*/
+ (BOOL)propertyIsOptional:(NSString *)propertyName;
/**
* Indicates whether the property with the given name is Ignored.
* To have a model with all of its properties being Ignored just return YES.
* This method returns by default NO, since the default behaviour is to have all properties required.
* @param propertyName the name of the property
* @return a BOOL result indicating whether the property is ignored
*/
+ (BOOL)propertyIsIgnored:(NSString *)propertyName;
/**
* Indicates the class used for the elements of a collection property.
* Rather than using:
* @property (strong) NSArray <MyType> *things;
* You can implement classForCollectionProperty: and keep your property
* defined like:
* @property (strong) NSArray *things;
* @param propertyName the name of the property
* @return Class the class used to deserialize the elements of the collection
*/
+ (Class)classForCollectionProperty:(NSString *)propertyName;
/**
* Merges values from the given dictionary into the model instance.
* @param dict dictionary with values
* @param useKeyMapping if YES the method will use the model's key mapper and the global key mapper, if NO
* it'll just try to match the dictionary keys to the model's properties
*/
- (BOOL)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping error:(NSError **)error;
@end