Ios: Serialize/Deserialize Complex JSON Generically from Nsobject Class

iOS: Serialize/Deserialize complex JSON generically from NSObject class

Finally we can solve this problem easily using JSONModel. This is the best method so far. JSONModel is a library that generically serialize/deserialize your object based on Class. You can even use non-nsobject based for property like int, short and float. It can also cater nested-complex JSON.

1) Deserialize example. By referring to above example, in header file:

#import "JSONModel.h"

@interface Person : JSONModel
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSNumber *age;
@end

@protocol Person;

@interface Department : JSONModel
@property (nonatomic, strong) NSMutableArray *accounting;
@property (nonatomic, strong) NSMutableArray *sales;
@end

in implementation file:

#import "JSONModelLib.h"
#import "myJSONClass.h"

NSString *responseJSON = /*from example*/;
Department *department = [[Department alloc] initWithString:responseJSON error:&err];
if (!err)
{
for (Person *person in department.accounting) {

NSLog(@"%@", person.firstName);
NSLog(@"%@", person.lastName);
NSLog(@"%@", person.age);
}

for (Person *person in department.sales) {

NSLog(@"%@", person.firstName);
NSLog(@"%@", person.lastName);
NSLog(@"%@", person.age);
}
}

2) Serialize Example. In implementation file:

#import "JSONModelLib.h"
#import "myJSONClass.h"

Department *department = [[Department alloc] init];

Person *personAcc1 = [[Person alloc] init];
personAcc1.firstName = @"Uee";
personAcc1.lastName = @"Bae";
personAcc1.age = [NSNumber numberWithInt:22];
[department.accounting addOject:personAcc1];

Person *personSales1 = [[Person alloc] init];
personSales1.firstName = @"Sara";
personSales1.lastName = @"Jung";
personSales1.age = [NSNumber numberWithInt:20];
[department.sales addOject:personSales1];

NSLog(@"%@", [department toJSONString]);

And this is NSLog result from Serialize example:

{ "accounting" : [{ "firstName" : "Uee",  
"lastName" : "Bae",
"age" : 22 }
],
"sales" : [{ "firstName" : "Sara",
"lastName" : "Jung",
"age" : 20 }
]}

iOS JSON serialization for NSObject-based classes

This is a tricky one because the only data you can put into JSON are straight up simple objects (think NSString, NSArray, NSNumber…) but not custom classes or scalar types. Why? Without building all sorts of conditional statements to wrap all of those data types into those type of objects, a solution would be something like:

//at the top…
#import

NSMutableDictionary *muteDictionary = [NSMutableDictionary dictionary];

id YourClass = objc_getClass("YOURCLASSNAME");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(YourClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
SEL propertySelector = NSSelectorFromString(propertyName);
if ([classInstance respondsToSelector:propertySelector]) {
[muteDictionary setValue:[classInstance performSelector:propertySelector] forKey:propertyName];
}
}
NSError *jsonError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:muteDictionary options:0 error:&jsonError];

This is tricky, though because of what I stated before. If you have any scalar types or custom objects, the whole thing comes tumbling down. If it's really critical to get something like this going, I'd suggest looking into investing the time and looking at Ricard's links which allow you to see property types which would assist on the conditional statements needed to wrap the values into NSDictionary-safe objects.

Serialize and Deserialize Objective-C objects into JSON

It sounds like you're looking for a serialization library that can let you convert objects of your own custom classes into JSON, and then reconstitute them back. Serialization of property-list types (NSArray, NSNumber, etc.) already exists in 3rd party libraries, and is even built into OS X 10.7 and iOS 5.

So, I think the answer is basically "no". I asked this exact question a month or two ago on the cocoa-dev mailing list, and the closest I got to a hit was from Mike Abdullah, pointing to an experimental library he'd written:

https://github.com/mikeabdullah/KSPropertyListEncoder

This archives objects to in-memory property lists, but as I said there are already APIs for converting those into JSON.

There's also a commercial app called Objectify that claims to be able to do something similar:

http://tigerbears.com/objectify/

It's possible I'll end up implementing what you're asking for as part of my CouchCocoa library, but I haven't dived into that task yet.

https://github.com/couchbaselabs/CouchCocoa

Serializing complex NSObject to JSON pattern

I'm not sure I understand the problem. You ask for a pattern, but you seem to describe the standard one:

Each one of these objects follows a protocol with a method which returns that objects properties in an NSDictionary with the appropriate keys.

Let's say that method is called serializedDictionary. If a class has properties that are themselves other objects, you just call serializedDictionary and add the result to the dictionary you are building. So all you need to do is ask the top-level object for its serializedDictionary, and convert that to JSON.

If you're worried about error handling, just check the result of the method and pass the error up to your caller. You could do this with exceptions (no code to write) or by convention. For example, say on an error you return nil and also by-reference a pointer to an NSError instance. Then in your container objects you do something like this:

- (NSDictionary *)serializedDictionaryWithError:(NSError **)error
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:self.someProperty forKey:@"some-property"];
NSDictionary *childDict = [self.childObject serializedDictionaryWithError:error];
if (childDict == nil) return nil;
[dict setObject:childDict forKey:@"child-object"];
return dict;
}

Bamn!

JSON to NSObject model tool

Give JSONExport a try:

JSONExport is a desktop application for Mac OS X which enables you to
export JSON objects as model classes with their associated
constructors, utility methods, setters and getters in your favorite
language.

Convert an iOS objective c object to a JSON string

EDIT: I have made a dummy app that should be a good example for you.

I create a Message class from your code snippet;

//Message.h
@interface Message : NSObject {
NSString *from_;
NSString *date_;
NSString *msg_;
}

@property (nonatomic, retain) NSString *from;
@property (nonatomic, retain) NSString *date;
@property (nonatomic, retain) NSString *msg;

-(NSDictionary *)dictionary;

@end

//Message.m
#import "Message.h"

@implementation Message

@synthesize from = from_;
@synthesize date = date_;
@synthesize msg = mesg_;

-(void) dealloc {
self.from = nil;
self.date = nil;
self.msg = nil;
[super dealloc];
}

-(NSDictionary *)dictionary {
return [NSDictionary dictionaryWithObjectsAndKeys:self.from,@"from",self.date, @"date",self.msg, @"msg", nil];
}

Then I set up an NSArray of two messages in the AppDelegate. The trick is that not only does the top level object (notifications in your case) need to be serializable but so do all the elements that notifications contains: Thats why I created the dictionary method in the Message class.

//AppDelegate.m
...
Message* message1 = [[Message alloc] init];
Message* message2 = [[Message alloc] init];

message1.from = @"a";
message1.date = @"b";
message1.msg = @"c";

message2.from = @"d";
message2.date = @"e";
message2.msg = @"f";

NSArray* notifications = [NSArray arrayWithObjects:message1.dictionary, message2.dictionary, nil];
[message1 release];
[message2 release];


NSError *writeError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:notifications options:NSJSONWritingPrettyPrinted error:&writeError];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"JSON Output: %@", jsonString);

@end

The output when I run the application is thus:

2012-05-11 11:58:36.018 stack[3146:f803] JSON Output: [
{
"msg" : "c",
"from" : "a",
"date" : "b"
},
{
"msg" : "f",
"from" : "d",
"date" : "e"
}
]

ORIGINAL ANSWER:

Is this the documentation you are looking for?

Sending a class through json post

As @Carl points out you have to convert it first to a JSON object, and then send it as a parameter on your POST request. Be aware that the back-end defines how your data should be send for requests. But this is the most common way of doing it.

Converting NSObject to NSDictionary

NSDictionary *details = {@"name":product.name,@"color":product.color,@"quantity":@(product.quantity)};

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:details
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];

if (! jsonData) {
NSLog(@"Got an error: %@", error);
} else {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}

Second part's source: Generate JSON string from NSDictionary in iOS



Related Topics



Leave a reply



Submit