I am having this weird issue. NSDictionary is not returning the correct integer value.
JSON response code from server.
{
"status":"ok",
"error_code":0,
"data" : [],
"msg":"everything is working!"
}
The JSON is being converted to a NSDictionary.
NSError *error = nil;
NSDictionary *jsonDict = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error: &error];
I access the NSDictionary value using the following code.
int error_code = (int)[jsonDict valueForKey:#"error_code"]
NSLog(#"%i", error_code);
The log outputs the following: 143005344
I've even tried objectForKey and I get the same response.
Thanks, in advance.
Yes it outputs the pointer of the value and that's why you see this log output.
You cannot cast the pointer to an integer and expect the value.
int error_code = [[jsonDict valueForKey:#"error_code"] integerValue];
or if you want to use modern objective-c
int error_code = [jsonDict[#"error_code"] integerValue];
Numbers are stored as NSNumber instances in plist/json dictionaries. Try calling one of NSNumber's getters like intValue:
int error_code = [jsonDict[#"error_code"] intValue];
Note also the new subscripting syntax for dictionaries.
Related
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!!
So I was working on a project that required me to work with some JSON, I was running into a few issues regarding the best way of representing things. First of, this is how the JSON looks:
"phoneList": [
{
"phoneReason": "End of Contract",
"phoneType": [
{
"id": 5,
"phoneType": "Android Smartphone"
}
]
}
]
I want to know the most appropriate way of representing this.
For example, I do know that that my phoneReason will just be a simple NSString while my phoneType is actually a NSArray. However,I wasn't sure how to represent a)the id, I know this is an integer, but should this be an NSInteger or an NSNumber and b)could someone point me in the direction of some sample code where I can understand how to model a dictionary object containing an integer and a string and also where I can understand how to model an array of dictionaries.
My other question is also similar in that say I'm actually posting something, how do I model this, specifically say for like dictionary type (JSON Curly Brace)objects that contain a number/integer and a string.
For example, this is the JSON I'm trying to model and then do something like this:
"phoneReason": "Upgrade",
"phoneInfo": {
"id": "2"
},
//And then I want to pass ID
-(void) createOurRequest:(NSNumber *)id {
NSDictionary *myDictionary = #{
#"phoneReason" : [NSString stringWithFormat:#"%i", s elf.dat.reason],
//How do I then represent the phoneInfo element exactly?
};
Sorry, for the clumsy question, would really appreciate any guidance on modeling JSON in iOS or just generally.
I'm assuming you're asking questions a) and b), and also how to model a JSON.
a) The unfortunate thing with Obj-C is that all collection elements have to be objects. Integers are value types, so they will need to be converted to NSNumbers to work. However, if you're parsing a JSON string, the builtin JSON parser does it for you. I'll describe it below.
b) The model is based on the JSON. You describe the object collection and the parser will determine the model for you. In your example, you would have a NSDictionary<NSString *: NSArray<NSDictionary<NSString *: id>*>*>. The innermost element has value of id because you can either have an NSString ("End of Contract") or an NSArray ("phoneType": [ { "id": 5, "phoneType": "Android Smartphone" } ])
Of course, the model is defined by your JSON, so if you run it through a parser, you get a structured object. You can access each element based on your model (object[#"phoneList"][#"phoneReason"]).
The class method to use is:
+ (id)JSONObjectWithData:(NSData *)data
options:(NSJSONReadingOptions)opt
error:(NSError **)error
Where you pass it a NSData representation of your string, options (or 0), and a NSError pointer (error*). You get back a parsed JSON with the proper structure you defined.
NSDictionary *parsedJSONObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:NULL
I have no options to use and I know there will be no error, so I pass nothing for those parameters. The resulting object will be in whatever structure your JSON is.
Using the objects and the json layout you provided in your first example, this is how I would go about creating the dictionaries and arrays to get the json in the format you specified. Hopefully this helps make it a little clearer for you.
// example constructor method
-(void) jsonStringWithPhoneReason:(NSString*)reason phoneId:(NSInteger)phoneId phoneType:(NSString*)phoneType
{
// create device detail dictionary
NSDictionary *deviceOneDetail = #{
#"id" : #(phoneId), // <- set phone id as NSNumber
#"phoneType" : phoneType // <- set your string phone type
};
// create device dictionary
NSDictionary *deviceOne = #{
#"phoneReason" : reason, // <- set your phone reason string
#"phoneType" : #[deviceOneDetail] // <- set your phone type dictionary within an array
};
// create phone list dictionary with any device dictionaries you want to add
NSDictionary *phoneListDict = #{
#"phoneList" : #[
deviceOne, // <- add your device to the phone list array of dictionaries
// deviceTwo...
]
};
NSString *jsonString = [self convertToJsonString:phoneListDict]; // <- convert the dictionary into a json string and use however you wish
// your json string should now look like this assuming you pass 'End of Contract', 5 & 'Android Smartphone' as arguments to this method
// {"phoneList":[{"phoneReason":"End of Contract","phoneType":[{"id":5,"phoneType":"Android Smartphone"}]}]}
}
-(NSString*) convertToJsonString:(NSDictionary*)dictionary
{
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary
options:0 // Pass 0 if you don't care about the readability of the generated string
error:&error];
if (error)
{
NSString *errorDesc = [NSString stringWithFormat:#"Error creating json data from dictionary: %#", error.localizedDescription];
NSLog(#"ERROR: %#", errorDesc);
jsonData = nil;
return nil;
}
NSString *returnString = nil;
if(jsonData != nil)
{
returnString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
return returnString;
}
I am trying to convert a JSON string into an object in Objective C using the code:
NSString *jsonString = (NSString *) responseObject;
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
The value of jsonString is
"[{\"Date\": \"12-01-2015\", \"Time\": \"7:00 am\", \"Title\":
\"First Car Service\", \"Details\": \"This was the first car
service ever done\"}]"
But the value of json is always nil. How do I convert the jsonString into a NSArray ?
My (third) bet: your json string isn't correct. If it contains the leading and trailing quotes strip them. Replaced the \" with ".
better: make the server or other json source send correct json.
From the error, it may be that your string is not formatted correctly, probably due to the quotes.
You should also make sure that after you have formatted the string, then you check the array has objects.
NSLog(#"JSON Details: %#", json[0][#"Details"]);
I am trying to use this code:
NSDictionary *innerMessage
= #{#"nonce":[NSNumber numberWithInteger:nonce],
#"payload":#{#"login": [NSNull null]}};
NSError * err;
NSData * innerMessageData = [NSJSONSerialization
dataWithJSONObject:innerMessage options:0
error:&err];
to create a JSON object with the following structure:
{
"apikey": "e418f5b4a15608b78185540ef583b9fc",
"signature": "FN6/9dnMfLh3wZj+cAFr82HcSvmwuniMQqUlRxSQ9WxRqFpYrjY2xlvDzLC5+qSZAHts8R7KR7HbjiI3SzVxHg==",
"message":{
"nonce": 12,
"payload": {
"Login": {}
}
}
}
However, this is the actual result which I get:
{"nonce":1398350092512,"payload":{"login":null}}
Why is [NSNull null] in my dictionary not being converted to {}?
How would I need to change my code to get the correct JSON
structure?
Thank you!
NSNull is suppose to become null in the JSON.
If you want an empty dictionary in the JSON ({}) you should use an empty dictionary - #{}.
Change code to
NSDictionary *innerMessage = #{
#"nonce":#12,
#"payload":#{#"login": #{}}
};
NSError * err;
NSData * innerMessageData = [NSJSONSerialization
dataWithJSONObject:innerMessage options:0
error:&err];
This will create the desired response
{
nonce = 12,
payload = {
login = {}
},
}
null is a perfectly valid JSON value; what were you expecting? How should NSJSONSerialization know that you wanted [NSNull null] to be converted to an empty object? (For that matter, why wouldn’t nulls be converted to an empty array, an empty list, or numeric zero?)
The solution is to process your innerMessage before you serialize it, replacing any instances of [NSNull null] with #{} (or, equivalently, [NSDictionary dictionary]).
In the following code for parsing a JSON, when objects happen to be other than NSArray or NSDictionary, NSJSONReadingAllowFragments is used.
The below code works fine and prints out 32. but if replace 32 by abcd, it outputs to null.
Any idea why its null for a string abcd.
NSString *num=#"32";
NSError *error;
NSData *createdData = [num dataUsingEncoding:NSUTF8StringEncoding];
id response=[NSJSONSerialization JSONObjectWithData:createdData options:NSJSONReadingAllowFragments error:&error];
NSLog(#"Response= %#",response);
That’s because 32 is a valid JSON fragment (a number), but abcd is not a valid JSON fragment since all strings must be quoted. Try:
NSString *num=#"\"abcd\"";
which produces "abcd" instead of abcd.
(also, bear in mind that the object being returned is not really an NSDictionary, so declaring it as id makes more sense)