SIGABRT when trying to parse JSON - objective-c

I am trying to parse a JSON string but it falls with a SIGABRT error.
Code I am using:
NSString *test = #'{"notifications":[{"id":"fae9a890-2791-46e2-ad9c-5a72f602a2e8","created":"2017-06-17T21:57:28+00:00","thread_id":3964,"reply_id":null,"thread":{"id":3964,"subject":"[CakePHP] Pagination"},"users_from":{"username":"Royal"},"content":"has posted a reply in"},{"id":"00732627-f23e-423e-b885-add968575972","created":"2017-06-17T20:08:05+00:00","thread_id":3964,"reply_id":79478,"thread":{"id":3964,"subject":"[CakePHP] Pagination"},"users_from":{"username":"Royal"},"content":"has quoted you in"}]}';
NSError *error;
NSMutableDictionary *allCourses = [NSJSONSerialization JSONObjectWithData:test
options:kNilOptions
error:&error];
if( error )
{
NSLog(#"%#", [error localizedDescription]);
}
else {
NSArray *monday = allCourses[#"notifications"];
for ( NSDictionary *theCourse in monday )
{
NSLog(#"----");
NSLog(#"Title: %#", theCourse[#"subject"] );
NSLog(#"Id: %#", theCourse[#"id"] );
NSLog(#"----");
}
}
Thanks.

The mistake is in your NSString declaration:
NSString *test = #'{"notifications"}';
This is wrong.
NSString must always use this format: #"bla bla bla".
You need to incorporate escapes for double quotes in your test string like this
NSString *test = #"{\"notifications\"}";

Related

How to parse JSON string in objective C? [duplicate]

This question already has answers here:
How do I parse JSON with Objective-C?
(5 answers)
Closed 6 years ago.
I have the following json:
NSString *s = #"{"temperature": -260.65, "humidity": 54.05, "time": "2016-03-14T09:46:48Z", "egg": 1, "id": 6950, "no2": 0.0}";
I need to extract data from json to strings
NSString temperature
NSString humidity
NSString no2
How to do it properly?
you can use NSJSONSerialization class. first you need to convert your string to an NSData object after that you will get the JSON data. have a look on the code
// json s string for NSDictionary object
NSString *s = #"{\"temperature\": -260.65, \"humidity\": 54.05, \"time\": \"2016-03-14T09:46:48Z\", \"egg\": 1, \"id\": 6950, \"no2\": 0.0}";
// comment above and uncomment below line, json s string for NSArray object
// NSString *s = #"[{\"ID\":{\"Content\":268,\"type\":\"text\"},\"ContractTemplateID\":{\"Content\":65,\"type\":\"text\"}}]";
NSData *jsonData = [s dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
// Note that JSONObjectWithData will return either an NSDictionary or an NSArray, depending whether your JSON string represents an a dictionary or an array.
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (error) {
NSLog(#"Error parsing JSON: %#", error);
}
else
{
if ([jsonObject isKindOfClass:[NSArray class]])
{
NSLog(#"it is an array!");
NSArray *jsonArray = (NSArray *)jsonObject;
NSLog(#"jsonArray - %#",jsonArray);
}
else {
NSLog(#"it is a dictionary");
NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
NSLog(#"jsonDictionary - %#",jsonDictionary);
}
}
After making the NSURL Request in the completion block u can do this:-
NSMutableDictionary *s = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSString *temperature =[s objectForKey:#"temperature"];
NSString *humidity = [s objectForKey:#"humidity"];

how to convert an array into string? [duplicate]

In my iPhone aplication I have a list of custom objects. I need to create a json string from them. How I can implement this with SBJSON or iPhone sdk?
NSArray* eventsForUpload = [app.dataService.coreDataHelper fetchInstancesOf:#"Event" where:#"isForUpload" is:[NSNumber numberWithBool:YES]];
SBJsonWriter *writer = [[SBJsonWriter alloc] init];
NSString *actionLinksStr = [writer stringWithObject:eventsForUpload];
and i get empty result.
This process is really simple now, you don't have to use external libraries,
Do it this way, (iOS 5 & above)
NSArray *myArray;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:myArray options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
I love my categories so I do this kind of thing as follows
#implementation NSArray (Extensions)
- (NSString*)json
{
NSString* json = nil;
NSError* error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&error];
json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return (error ? nil : json);
}
#end
Although the highest voted answer is valid for an array of dictionaries or other serializable objects, it's not valid for custom objects.
Here is the thing, you'll need to loop through your array and get the dictionary representation of each object and add it to a new array to be serialized.
NSString *offersJSONString = #"";
if(offers)
{
NSMutableArray *offersJSONArray = [NSMutableArray array];
for (Offer *offer in offers)
{
[offersJSONArray addObject:[offer dictionaryRepresentation]];
}
NSData *offersJSONData = [NSJSONSerialization dataWithJSONObject:offersJSONArray options:NSJSONWritingPrettyPrinted error:&error];
offersJSONString = [[NSString alloc] initWithData:offersJSONData encoding:NSUTF8StringEncoding] ;
}
As for the dictionaryRepresentation method in the Offer class:
- (NSDictionary *)dictionaryRepresentation
{
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
[mutableDict setValue:self.title forKey:#"title"];
return [NSDictionary dictionaryWithDictionary:mutableDict];
}
Try like this Swift 2.3
let consArray = [1,2,3,4,5,6]
var jsonString : String = ""
do
{
if let postData : NSData = try NSJSONSerialization.dataWithJSONObject(consArray, options: NSJSONWritingOptions.PrettyPrinted)
{
jsonString = NSString(data: postData, encoding: NSUTF8StringEncoding)! as String
}
}
catch
{
print(error)
}
Try like this,
- (NSString *)JSONRepresentation {
SBJsonWriter *jsonWriter = [SBJsonWriter new];
NSString *json = [jsonWriter stringWithObject:self];
if (!json)
[jsonWriter release];
return json;
}
then call this like,
NSString *jsonString = [array JSONRepresentation];
Hope it will helps you...
I'm a bit late to this party, but you can serialise an array of custom objects by implementing the -proxyForJson method in your custom objects. (Or in a category on your custom objects.)
For an example.

Strange NSData Output

I have some unexpected results coming from the following code:
- (NSData *)postDataWithDict:(NSDictionary *)postDict
{
// Assume key is urlValid
NSUInteger postCount = [postDict count];
NSMutableArray *buildArray = [[NSMutableArray alloc] initWithCapacity:postCount];
for (NSString *key in postDict) {
//post data is key=value&key=value&key=value...
// start with key
NSMutableString *arrayLine = [NSMutableString stringWithString:key];
[arrayLine appendString:#"="];
// analyze and then append value
id postValue = [postDict objectForKey:key];
if ([postValue isKindOfClass:[NSNumber class]]) {
NSString *valueString = [NSString stringWithFormat:#"%#",postValue];
[arrayLine appendString:valueString];
}
else if ([postValue isKindOfClass:[NSString class]]) {
NSString *urlEncodedString = [self urlEncodeValue:postValue];
[arrayLine appendString:urlEncodedString];
}
else {
NSLog(#"postKey: %#, postValue class:%#", key, [postValue class]);
NSError *jsonError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:postValue
options:0
error:&jsonError];
if (jsonError != nil) {
NSLog(#"JSON serialization failed: %# - %#", [jsonError localizedDescription], [jsonError userInfo]);
NSLog(#"value: %#", postValue);
}
else {
// need to urlencode
NSString *stringifyJSON = [NSString stringWithUTF8String:[jsonData bytes]];
NSString *urlJSONstring = [self urlEncodeValue:stringifyJSON];
[arrayLine appendString:urlJSONstring];
}
}
[buildArray addObject:arrayLine];
}
NSString *postString = [buildArray componentsJoinedByString:#"&"];
NSData *postData = [postString dataUsingEncoding:NSUTF8StringEncoding];
//testing
NSLog(#"Post Dict: %#", postDict);
NSLog(#"Post Array: %#", buildArray);
NSLog(#"Post String: %#", postString);
NSLog(#"Post Data: %#", [NSString stringWithUTF8String:[postData bytes]]);
return postData;
}
My //testing log results:
Post Dict: {
authenticationString = b3210c0bc6d2c47f4c2f7eeea12e063d;
dataMode = updateSingle;
dateCreated = "374300293.81108";
dateModified = "374609294.313093";
dateSynced = "374610683.588062";
entityName = CommodityTypes;
myName = 21;
sortKey = 21;
username = iPhoneAdamek;
usernameString = iPhoneAdamek;
uuidKey = "53403EAE-DD4F-4226-A979-316EF7F43991";
}
Post Dict looks good. Just what I wanted.
2012-11-14 13:31:23.640 FoodyU[11393:907] Post Array: (
"myName=21",
"dataMode=updateSingle",
"dateSynced=374610683.588062",
"uuidKey=53403EAE-DD4F-4226-A979-316EF7F43991",
"sortKey=21",
"dateModified=374609294.313093",
"entityName=CommodityTypes",
"dateCreated=374300293.81108",
"authenticationString=b3210c0bc6d2c47f4c2f7eeea12e063d",
"usernameString=iPhoneAdamek",
"username=iPhoneAdamek"
)
Post Array looks good. Strings are all set to be concatenated for a HTTP POST string.
2012-11-14 13:31:23.641 FoodyU[11393:907] Post String: myName=21&dataMode=updateSingle&dateSynced=374610683.588062&uuidKey=53403EAE-DD4F-4226-A979-316EF7F43991&sortKey=21&dateModified=374609294.313093&entityName=CommodityTypes&dateCreated=374300293.81108&authenticationString=b3210c0bc6d2c47f4c2f7eeea12e063d&usernameString=iPhoneAdamek&username=iPhoneAdamek
Post String looks good. I'm ready to convert it to data to use in [NSMutableURLRequest setHTTPBody:postData].
2012-11-14 13:31:23.643 FoodyU[11393:907] Post Data: myName=21&dataMode=updateSingle&dateSynced=374610683.588062&uuidKey=53403EAE-DD4F-4226-A979-316EF7F43991&sortKey=21&dateModified=374609294.313093&entityName=CommodityTypes&dateCreated=374300293.81108&authenticationString=b3210c0bc6d2c47f4c2f7eeea12e063d&usernameString=iPhoneAdamek&username=iPhoneAdamekoneAdamek;
usernameString = iPhoneAdamek;
uuidKey = "53403EAE-DD4F-4226-A
WTF??? How did &username=iPhoneAdamek become &username=iPhoneAdamekoneAdamek;
usernameString = iPhoneAdamek;
uuidKey = "53403EAE-DD4F-4226-A?
I'm fairly new to Cocoa. Is there something wrong with:
NSData *postData = [postString dataUsingEncoding:NSUTF8StringEncoding];
or
NSLog(#"Post Data: %#", [NSString stringWithUTF8String:[postData bytes]]);
You shouldn't be using NSLog of NSData as,
NSLog(#"Post Data: %#", [NSString stringWithUTF8String:[postData bytes]]);
Instead use it as,
NSLog(#"Post Data: %#", [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding]);
[NSString stringWithUTF8String:[postData bytes]] always returns unexpected results.
As per documentation for bytes,
bytes: Returns a pointer to the receiver’s contents.
And as per Apple documentation for stringWithUTF8String,
stringWithUTF8String:
Returns a string created by copying the data from a given C array of UTF8-encoded bytes.
Parameters: bytes - A NULL-terminated C array of bytes in UTF8 encoding.
So when you are using [postData bytes], it is not NULL-terminated and hence when you are using with stringWithUTF8String returns the data written in memory till it encounters a NULL-termination.

JSONKit Parsing Nested JSON with Objective-C

I am trying to parse my nested JSON with JSONKit and the 2nd level JSON isn't being parsed correctly.
Here's sample JSON...
{
"app": {
"content": "[{\\\"Id\\\":\\\"1\\\",\\\"Name\\\":\\\"John\\\"},{\\\"Id\\\":\\\"2\\\",\\\"Name\\\":\\\"John\\\"}]"
}
}
and Here's my code...
NSString *jsonString = "...long nested json string...";
NSDictionary *jsonParsed = [jsonString objectFromJSONString];
NSString *content = [[jsonParsed objectForKey:#"app"] objectForKey:#"content"];
NSDictionary *jsonContent = [content objectFromJSONString];
NSLog(#"%#", jsonContent);
Where am I going wrong?
This is quite easy to answer: You are escaping \ as well as ". So your result in the NSString* content will be \". This is something your JSON parser won't digest. So use instead of \\\" this \".
If you replace the content string with following:
"[{\"Id\":\"1\",\"Name\":\"John\"},{\"Id\":\"2\",\"Name\":\"John\"}]"
It will be parsed correctly.
JSON.parse("[{\"Id\":\"1\",\"Name\":\"John\"},{\"Id\":\"2\",\"Name\":\"John\"}]")
>>> [Object { Id="1", Name="John"}, Object { Id="2", Name="John"}]
Maybe you have escaped the content string twice at somewhere in your code.
I just used firebug to see if the JSON was correct. JSONKit is the same:
clowwindy:~ clowwindy$ cat /tmp/input.txt
{
"app": {
"content": "[{\"Id\":\"1\",\"Name\":\"John\"},{\"Id\":\"2\",\"Name\":\"John\"}]"
}
}
NSError *error;
NSString *input = [NSString stringWithContentsOfFile:#"/tmp/input.txt" encoding:NSUTF8StringEncoding error:&error];
NSString *jsonString = input;
NSDictionary *jsonParsed = [jsonString objectFromJSONString];
NSString *content = [[jsonParsed objectForKey:#"app"] objectForKey:#"content"];
NSDictionary *jsonContent = [content objectFromJSONString];
NSLog(#"%#", jsonContent);
NSLog(#"%#", content);
2012-01-02 00:26:39.818 testjson[12700:707] (
{
Id = 1;
Name = John;
},
{
Id = 2;
Name = John;
}
)
2012-01-02 00:26:39.822 testjson[12700:707] [{"Id":"1","Name":"John"},{"Id":"2","Name":"John"}]

Can't read file

Here is my method which reads content of file. Unfortunately doesn't work for me. The path to file is correct. What I miss ?
- (IBAction)readFile:(id)sender
{
NSString *str = [NSString stringWithContentsOfFile:#"/Users/joe/text.txt"
encoding:NSUTF32StringEncoding
error:nil
];
NSLog(#"%#", str); //Result is null
}
Try using the built-in functionality of stringWithContentsOfFile:encoding:error: and give it a NSError and you can see exactly whats wrong:
- (IBAction)readFile:(id)sender {
NSError *readFileError = nil;
NSString *str = [NSString stringWithContentsOfFile:#"/Users/joe/text.txt"
encoding:NSUTF32StringEncoding
error:&readFileError
];
if (readFileError) {
NSLog(#"%# - %#", [readFileError localizedDescription], [readFileError localizedFailureReason]);
} else {
NSLog(#"%#", str);
}
}