5

I am currently trying to work with json and objective-c however having a bit of difficulty. The following is the json that is being returned

{
    sethostname =     (
    {
        msgs = "Updating Apache configuration\nUpdating cPanel license...Done. Update succeeded.\nBuilding global cache for cpanel...Done";
        status = 1;
        statusmsg = "Hostname Changed to: a.host.name.com";
        warns =             (
        );
    });
}

I am able to check that the response is coming back and the key is sethostname however no matter what I try I cannot get for example the value of status or statusmsg. Can anyone point me in the right location. The following is basic code I am using to check that sethostname is returned.

NSError *myError = nil;
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&myError];
NSLog([res description]);
NSArray *arr;
arr = [res allKeys];
if ([arr containsObject:@"sethostname"])
{
    NSLog(@"worked");
}
Peter
  • 773
  • 1
  • 7
  • 23
  • 3
    What happens when you run this code? What if you just log `res`? – jtbandes Aug 20 '11 at 21:52
  • when I run this code worked is displayed in the output however no matter what I try I cannot retrieve the value of status or any of the other sub keys. – Peter Aug 20 '11 at 22:30

3 Answers3

11

When in doubt, write down the structure of your JSON data. For example:

{
    sethostname =     (
    {
        msgs = "Updating Apache configuration\nUpdating cPanel license...Done. Update succeeded.\nBuilding global cache for cpanel...Done";
        status = 1;
        statusmsg = "Hostname Changed to: a.host.name.com";
        warns =             (
        );
    });
}

(which is in NeXTSTEP property list format, actually) means that you have a top-level dictionary. This top-level dictionary contains a key called sethostname whose value is an array. This array is comprised of dictionaries, each dictionary having a set of keys: msgs, status, statusmsg, warns. msgs has a string value, status has a number value, statusmsg has a string value,warns` has an array value:

dictionary (top-level)
    sethostname (array of dictionaries)
        dictionary (array element)
            msgs (string)
            status (number)
            statusmsg (string)
            warns (array)
                ??? (array element)

Having understood this structure, your code should look like:

NSError *myError = nil;
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&myError];

if (!res) { // JSON parser failed }

// dictionary (top-level)
if (![res isKindOfClass:[NSDictionary class]]) {
    // JSON parser hasn't returned a dictionary
}

// sethostname (array of dictionaries)
NSArray *setHostNames = [res objectForKey:@"sethostname"];

// dictionary (array element)
for (NSDictionary *setHostName in setHostNames) {
    // status (number)
    NSNumber *status = [setHostName objectForKey:@"status"];

    // statusmsg (string)
    NSString *statusmsg = [setHostName objectForKey:@"statusmsg"];

    …
}
  • Forgot to thank you for this reply. This answer pointed me in exactly the right direction and gave good methods for deciphering my results. – Peter Oct 10 '12 at 12:25
1

Why not use the simplest JSON method - [myString jsonValue];

It's part of this JSON framework for objective-c

Alex Coplan
  • 13,211
  • 19
  • 77
  • 138
  • Hi Alex. what package is jsonValue a part of I am using the NSJSONSerialization which is a part of the foundation framework. – Peter Aug 20 '11 at 22:13
  • Ahh ok Alex, a different package. I had actually looked at using this before however I am using automatic reference counting and these packages have not been updated for this as of yet. That particular package did have a released version that worked but this was retracted as soon as he realised it did not work with reference counting turned off. – Peter Aug 20 '11 at 22:29
0

I don't think if ([arr containsObject:@"sethostname"]) is going to work, because the results array is not going to contain that exact object. It might contain an object with the same content, but it won't be the SAME object.

As jtbandes wrote, you need to log the actually output. NSLog both res and arr and see what you have.

Flyingdiver
  • 2,142
  • 13
  • 18
  • Hi Flyingdiver the keys from the original json are put into the array and the if statement checks if an object with the same value is in the array the if statement passes. I have checked this bit is working and it does appear to be (hence the nslog) – Peter Aug 20 '11 at 22:12
  • So, what do res and arr actually contain (NSLog output, please)? – Flyingdiver Aug 20 '11 at 22:49
  • it looks like a part of the problem I was having is that I was wrong in what I thought they did contain. Bavarious Has cleared this up a bit – Peter Aug 21 '11 at 14:46