Binding KVC-based JSON to data objects on iOS platform

Source: Internet
Author: User

Binding KVC-based JSON to data objects on iOS platform
 

On the iOS platform, it is not difficult to manipulate JSON data. However, we still have a simpler solution, using KVC, the full name is Key-Value Coding.

Assume that the developer (you) has developed an application whose data comes from external services and needs to retrieve some JSON data from the Web service. The data is as follows:

{count: 3, sum: 9.0, average: 3.0}

To obtain data from the server, you must call the JSONObjectWithData method of NSJSONSerializationalization and retrieve data from the deserialization dictionary, for example:

NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];NSLog(@%d, [[dictionary objectForKey:@count] intValue]); // prints 3RdNSLog(@%.1f, [[dictionary objectForKey:@sum] doubleValue]); // prints 9.0NSLog(@%.1f, [[dictionary objectForKey:@average] doubleValue]); // prints 3.0

However, the above values are scattered. During application development, you may want to directly interact with strong data objects, which makes it easier. For example, you may want to create a Statistics class to represent the data types returned by the Web service, as shown below:

@interface Statistics : NSObject@property (nonatomic) int count;@property (nonatomic) double sum;@property (nonatomic) double average;@end

Then, you can extract values from the dictionary to fill the above objects:

Statistics *statistics = [[Statistics alloc] init];statistics.count = [[dictionary objectForKey:@count] intValue];statistics.sum = [[dictionary objectForKey:@sum] doubleValue];statistics.average = [[dictionary objectForKey:@average] doubleValue];

To make things easier and avoid code duplication, you can put this code in the initialization of the Statistics class:

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {    self = [super init];    if (self) {        self.count = [[dictionary objectForKey:@count] intValue];        self.sum = [[dictionary objectForKey:@sum] doubleValue];        self.average = [[dictionary objectForKey:@average] doubleValue];    }    return self;}

The Code binds JSON to respond to the Statistics instance, as follows:

Statistics *statistics = [[Statistics alloc] initWithDictionary:dictionary];

In any case, you can use the attribute of this strong data object to access the data returned from the server:

NSLog(@%d, statistics.count); // prints 3NSLog(@%.1f, statistics.sum); // prints 9.0NSLog(@%.1f, statistics.average); // prints 3.0

The above code works normally, and it is very suitable to map JSON data to strongly typed data objects.

However, there is a simpler solution: KVC. SetValuesForKeysWithDictionary of NSObject: This method can be used to automatically map all values in a given dictionary to the attributes of an object. Using this method, initWithDictionary: The method is simplified as follows:

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {    self = [super init];    if (self) {        [self setValuesForKeysWithDictionary:dictionary];    }    return self;}

You do not need to manually map the dictionary to the item to the attribute value. It is enough to declare the attribute with the appropriate name and type. Swift works well in the following code:

class Statistics: NSObject {    var count: Int = 0    var sum: Double = 0    var average: Double = 0    init(dictionary: [String:AnyObject]) {        super.init()        setValuesForKeysWithDictionary(dictionary);    }}

In addition, if you need to customize the attribute name or attribute value allocation, you can simply override setValue: forKey: method. For example, assume that the server uses different names to reference the average attribute:

{count: 3, sum: 9.0, mean: 3.0}

You can override setValue: forKey: method to ensure that the value is correctly mapped to the attribute:

- (void)setValue:(id)value forKey:(NSString *)key {    if ([key isEqual:@mean]) {        key = @average;    }    [super setValue:value forKey:key];}

Finally, you can use KVC to ignore values you don't want. For example, assume that the server response also contains the "median" attribute:

{count: 3, sum: 9.0, average: 3.0, median: 3.0}

Because the Statistics class does not define the "Median" attribute, setValuesForKeysWithDictionary: The method throws an NSUnknownKeyException. To avoid throwing this exception, you can simply override setValue: forUndefinedKey: method.

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {    // No-op}

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.