Error in JSON encode - ios

I have a problem when encode an NSMutableArray array of custom object (Room).
My custom object is : -nameRoom (NSString) -numberRoom (NSInteger).
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
This is the error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Room)
Thanks.

From the docs (yes, sometimes reading the documentation is helpful)
You use the NSJSONSerialization class to convert JSON to Foundation
objects and convert Foundation objects to JSON.
An object that may be converted to JSON must have the following
properties:
The top level object is an NSArray or NSDictionary.
All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
All dictionary keys are instances of NSString.
Numbers are not NaN or infinity.
Other rules may apply. Calling isValidJSONObject: or attempting a
conversion are the definitive ways to tell if a given object can be
converted to JSON data.

JSON does not support custom objects.
See: Introducing JSON.
In order to support a custom object you will have to break it down into a graph of standard JSON objects. In the OP's case it will simply be a dictionary containing nameRoom and numberRoom.

Related

CFPropertyListCreateDeepCopy returns nil if any value is NULL

I am using the following CoreFoundation function CFPropertyListCreateDeepCopy:
for converting the immutable objects to mutable objects.If any of the object is NULL the CFPropertyListCreateDeepCopy returning empty .Is there any work around for this.
self.packageArray = CFBridgingRelease(CFPropertyListCreateDeepCopy(NULL, (CFPropertyListRef)self.packageArray , kCFPropertyListMutableContainersAndLeaves));
CFPropertyListCreateDeepCopy fails to process array / dictionary containing NSNull
sample code
NSArray *immutable = #[ #"a", [NSNull null], #"c" ];
NSMutableArray *mutable = (__bridge
id)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (__bridge
CFArrayRef)immutable, kCFPropertyListMutableContainers);
sample json response from this link
Thanks in advance.
After few hours of workaround, I have solved this issue by below way.
Just place below line when converting API response to JSON Object.
responseString=[responseString stringByReplacingOccurrencesOfString:#"\":null" withString:#"\":\"\""];//To Handle Null Characters
//Search for below line in your parsing library and paste above code
data = [responseString dataUsingEncoding:NSUTF8StringEncoding];
So there will be no null characters in your JSON object, hence no issue with using CFPropertyListCreateDeepCopy.
Cheers!!

JSON parse returns NSDicationary with empty values

I'm trying to transform a very simple JSON in to a NSDicationary to then populate my CoreData model with the retrieved data, the problem is after I get my json from the server and try to parse it to a NSDicationary my dictionary just show I have 811 values inside but they all are empry values.
I have printed my json (NSData) and all the content is there and my error var is null after this point.
This is the piece of code I use to do the parse:
[NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error]
And here is an example of my JSON:
[
{
"product": "A",
"name": "B"
},
{
"product": "B",
"name": "A"
}
]
If I print the data using the code below, the result is exactly the same I get from my server:
[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]
After clicking in the "I" (information) icon I got that:
Execution was interrupted, reason: Attempted to dereference an invalid
ObjC Object or send it an unrecognized selector. The process has been
returned to the state before expression evaluation.
But can't understand why...
I have already searched for this on stackoverflow and I didn't find any solution to my problem, maybe I'm searching with the wrongs terms.
You say you are parsing your JSON into an NSDictionary but the top-level data structure of your JSON is an array. Parse your JSON into an NSArray; each element of this array will be an NSDictionary.

JSon array to core data entity

I have a cuestion about parsing a Json strings.
If i'm getting a string like:
[["AR","Argentina","flag_of_argentina","en","F","1"],
["AU","Australia","flag_of_‌​australia","en","B","4"]]
How can i save this string into an entity when normally i see Jsons that have something like this:
(
(
"Group_id": 1,
"Date" : "2014-04-08",
"Hour" : "18:00:00",
"Location":"Guayaquil, Ecuador",
"State" : A
),
...
If i have to make an array or something else to store it to the entity in core data how can i do it?
I hope my question is well made ​​and I appreciate your help. Thank you very much.
Cocoa Touch provides a built in class that helps you serialize this data. It's called NSJSONSerialization.
So, that looks to me like you have arrays within an array. First you're going to want to convert the NSString to NSData:
NSData *JSONdata = [yourJSONString dataUsingEncoding:NSUTF8StringEncoding];
Then serialize it into an array:
NSArray *JSONArray = [NSJSONSerialization JSONObjectWithData:JSONdata options:NSJSONReadingMutableContainers error:&error];
Then you can access any subarray by writing:
NSArray *countryData = [JSONArray objectAtIndex:i];
And from there you can access the data that you need.
~
As for building JSON Data, you'll need to construct an NSMutableDictionary and populate it accordingly. Once you have that, use the same class NSJSONSerialization to convert it to a JSON string.

Crash when grabbing specific ABPerson's image

I am grabbing images from the users' contacts in their iOS Address Book/Contacts.app. And putting them in a dictionary to upload as JSON.
I am getting the following error:
2012-12-05 10:38:01.286 ContactsApp[6247:713f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (__NSCFData)'
*** First throw call stack:
(0x2de6012 0x286ce7e 0x2de5deb 0x20926fe 0x2096b21 0x2dd3cdf 0x2dd387d 0x2dd37c5 0x20966fa 0x209262d 0x2096b21 0x2dd3cdf 0x2dd387d 0x2dd37c5 0x20966fa 0x209262d 0x20969af 0x2ddfe7c 0x2ddfa16 0x2ddf925 0x20968b8 0x2092679 0x2096b21 0x2dd3cdf 0x2dd387d 0x2dd37c5 0x20966fa 0x209262d 0x20923bd 0x209579c 0x1cad5 0x67475 0x66a87 0x14399cd 0x746008f 0x3dc253f 0x3dd4014 0x3dc52e8 0x3dc5450 0x90e36e12 0x90e1ecca)
libc++abi.dylib: terminate called throwing an exception
I've using the following code:
if (ABPersonHasImageData(addressBookContact)) {
NSMutableDictionary *imageDictionary = [NSMutableDictionary dictionary];
NSData *thumbnailImageData = (__bridge NSData *)ABPersonCopyImageDataWithFormat(addressBookContact, kABPersonImageFormatThumbnail);
NSData *originalImageData = (__bridge NSData *)ABPersonCopyImageDataWithFormat(addressBookContact, kABPersonImageFormatOriginalSize);
if (thumbnailImageData) [imageDictionary setObject:thumbnailImageData forKey:#"thumbnailImage"];
if (originalImageData) [imageDictionary setObject:originalImageData forKey:#"originalImage"];
[contactDictionary setObject:imageDictionary forKey:#"image"];
}
The error occurs when I am trying to place the array into this request:
[addressBookArray addObject:contactDictionary];
if ([addressBookArray count] % 15 == 0) {
// I'm using AFNetworking
[[APIClient sharedClient] requestWithMethod:#"POST" path:#"cmd/addContact" parameters:#{ #"addressBookEntries" : addressBookArray }];
[addressBookArray removeAllObjects];
}
Your problem is that you are attempting to put NSData objects into a JSON object. Instead of adding the image data to the imageDictionary, add the base64 encoding of the images to the imageDictionary and you should have no problem.
Matt Gallagher has a handy class for handling base64 here: http://www.cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html
Looks like AFNetworking is trying to parse your parameters into JSON, but you're passing it an NSData. Although your passing it an NSDictionary, which is valid, those nested types need to be either other NSDictionaries, NSArrays, NSStrings, and NSNumbers. If you want to append image NSDatas, you have to use a different content-type and append the image data.

How to parse JSON in iOS App

Im getting a response from twitter in the form of a string,
What I need is to send the parts where is a comment to an array,
here an example of the string
[{"geo":null,"coordinates":null,"retweeted":false,...
"text":"#KristinaKlp saluditos y besos d colores!"},{"geo":null,"coordinates...
so what I really need are the posts after "text":" =
#KristinaKlp saluditos y besos d colores!
So, how can I take the string and parse it so I get all the messages in an array hopefully?
Thanks a lot!
I haven't done JSON parsing myself in an iOS App, but you should be able to use a library like the json-framework. This library will allow you to easily parse JSON and generate json from dictionaries / arrays (that's really all JSON is composed of).
SBJson docs:
JSON is mapped to Objective-C types in the following way:
null -> NSNull
string -> NSString
array -> NSMutableArray
object -> NSMutableDictionary
true -> NSNumber's -numberWithBool:YES
false -> NSNumber's -numberWithBool:NO
integer up to 19 digits -> NSNumber's -numberWithLongLong:
all other numbers -> NSDecimalNumber
Since Objective-C doesn't have a dedicated class for boolean values,
these turns into NSNumber instances. However, since these are
initialised with the -initWithBool: method they round-trip back to JSON
properly. In other words, they won't silently suddenly become 0 or 1;
they'll be represented as 'true' and 'false' again.
As an optimisation integers up to 19 digits in length (the max length
for signed long long integers) turn into NSNumber instances, while
complex ones turn into NSDecimalNumber instances. We can thus avoid any
loss of precision as JSON allows ridiculously large numbers.
#page objc2json Objective-C to JSON
Objective-C types are mapped to JSON types in the following way:
NSNull -> null
NSString -> string
NSArray -> array
NSDictionary -> object
NSNumber's -initWithBool:YES -> true
NSNumber's -initWithBool:NO -> false
NSNumber -> number
#note In JSON the keys of an object must be strings. NSDictionary
keys need not be, but attempting to convert an NSDictionary with
non-string keys into JSON will throw an exception.
NSNumber instances created with the -numberWithBool: method are
converted into the JSON boolean "true" and "false" values, and vice
versa. Any other NSNumber instances are converted to a JSON number the
way you would expect.
Tutorials
Are there any tutorials? Yes! These are all tutorials provided by
third-party people:
JSON Framework for iPhone - a Flickr tutorial in three parts by John
Muchow. JSON Over HTTP On The iPhone - by Dan Grigsby. AS3 to Cocoa touch: JSON by Andy Jacobs.
There are other libraries you can check out as well like TouchJSON, JSONKit, Yet Another JSON Library
NSJSONSerialization does the job of converting your JSON data into usable data structures as NSDictionary or NSArray very well. I recommend it, even more because it is part of the Cocoa public interface and it is maintained by Apple.
However, if you want to map the content of your JSON to your Objective-C objects, you will have to map each attribute from the NSDictionary/NSArray to your object property. This might be a bit painful if your objects have many attributes.
In order to automatise the process, I recommend you to use the Motis category (personal project) on NSObject to accomplish it, thus it is very lightweight and flexible. You can read how to use it in this post. But just to show you, you just need to define a dictionary with the mapping of your JSON object attributes to your Objective-C object properties names in your NSObject subclasses:
- (NSDictionary*)mjz_motisMapping
{
return #{#"json_attribute_key_1" : #"class_property_name_1",
#"json_attribute_key_2" : #"class_property_name_2",
...
#"json_attribute_key_N" : #"class_property_name_N",
};
}
and then perform the parsing by doing:
- (void)parseTest
{
NSData *data = jsonData; // <-- YOUR JSON data
// Converting JSON data into NSArray (your data sample is an array)
NSError *error = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if (error)
return; // <--- If error abort.
// Iterating over raw objects and creating model instances
NSMutableArray *parsedObjects = [NSMutableArray array];
for (NSDictionary *rawObject in jsonArray)
{
// Creating an instance of your class
MyClass instance = [[MyClass alloc] init];
// Parsing and setting the values of the JSON object
[instance mjz_setValuesForKeysWithDictionary:rawObject];
[parsedObjects addObject:instance];
}
// "parseObjects" is an array with your parsed JSON.
// Do whatever you want with it here.
}
The setting of the properties from the dictionary is done via KeyValueCoding (KVC) and you can validate each attribute before setting it via KVC validation.
I recently had to do this. After looking at the various options out there, I threw JSONKit into my app (I found it on a JSON discussion on StackOverflow). Why?
A) It is VERY VERY simple. I mean, all it has is the basic parsing/emitting functions, what more do you need?
B) It is VERY VERY fast. No overhead - just get the job done.
I should note, I had never done JSON before - only heard of the term and didn't even know how to spell it. I went from nothing, to a working app, in about 1 hour. You just add one class to your app (the .h, .m), instantiate it, and call the parser to a dictionary object. Voila. If it contains an array, you just get the objectForKey, cast it as an NSArray. It's really hard to get simpler than that, and very fast.
For a good comparison of the speed of the different libraries for JSON parsing on iOS, take a look at The Ultimate Showdown.
-(IBAction)btn_parse_webserivce_click:(id)sender
{
// Take Webservice URL in string.
NSString *Webservice_url = self.txt_webservice_url.text;
NSLog(#"URL %#",Webservice_url);
// Create NSURL from string.
NSURL *Final_Url = [NSURL URLWithString:Webservice_url];
// Get NSData from Final_Url
NSData* data = [NSData dataWithContentsOfURL:
Final_Url];
//parse out the json data
NSError* error;
// Use NSJSONSerialization class method. which converts NSData to Foundation object.
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
// Create Array
NSArray* Response_array = [json objectForKey:#"loans"];
NSLog(#"Array: %#", Response_array);
// Set Response_array to textview.
self.txt_webservice_response.text = [NSString stringWithFormat:#"%#"
,Response_array];
}
How about NSJSONSerialization? I've been using it to parse JSON
http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html

Resources