0

I need to parse a json string to a NSMutableArray... I did it as follows:

    JsonString = "{
   "list":[
      {
         "IDI":{
            "IDI_ID":1
         },
         "PAR_VPARAM":"param1",
         "PAR_VALUE":"value1"
      },
      {
         "IDI":{
            "IDI_ID":2
         },
         "PAR_VPARAM":"param2",
         "PAR_VALUE":"value2"
      },
      {
         "IDI":{
            "IDI_ID":3
         },
         "PAR_VPARAM":"param3",
         "PAR_VVALUE":"value3"
      }
   ]
}";


NSData *data = [JsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&err];
NSMutableArray *resultArray = [json objectForKeyedSubscript:@"list"];

I have an object called PARAMETERS, and it has the same structure of a single item of JSON: "list". When i parse it, it works, the problem is in the object inside of each item in the json: "IDI", always parse with null value.

for(NSObject *obj in resultArray){
     Parameters *paritem = (Parameters *)obj;
     int test = paritem.IDI.IDI_ID; //Error here!
}

How can i do it?

1
  • If you want a mutable array, use option NSJSONReadingMutableContainers. Commented Jun 5, 2014 at 15:47

2 Answers 2

2

NSJSONSerialization won't map your JSON data to your custom class. It will provide NSString, NSNumber, NSDictionary, and NSArray objects (or their mutable counterparts, if you specify the right NSJSONReadingOptions).

If you want to map this data to your Parameters class, you have to provide that logic yourself. You cannot simply cast NSDictionary.

for(NSObject *obj in resultArray){
    Parameters *paritem = [[Parameters alloc] init];

    paritem.PAR_VPARAM = obj[@"PAR_VPARAM"];
    paritem.PAR_VALUE = obj[@"PAR_VALUE"];

    // To capture the IDI property, you will either have to
    // define a new IDI class with a property named "IDI_ID",
    // live with NSDictionary, or add an "IDI_ID" property
    // to your Parameters class.

    // In this example, I left the value as a dictionary.
    paritem.IDI = obj[@"IDI"];

    // Here's how you would get the IDI_ID:
    NSNumber *IDI_ID = paritem.IDI[@"IDI_ID"];
}

With that out of the way, here are a couple unsolicited stylistic tips:

  • For variables and properties in Obj-C, lowerCamelCase is conventional. Instead of paritem.PAR_VPARAM, use parItem.parVParam (note the capital I in parItem).
  • Your class names should have a two- or three-letter "namespace" (much like NSString, UIView, or CGPoint). If you can't come up with a couple letters to represent this specific project, use an abbreviation of your company's name. If all else fails, use your initials.
  • Your parameter names are extremely vague, and somewhat redundant. Does every property really need to be prefixed with PAR_? Do you really need IDI_ID to be nested within the IDI property of your Parameters object? You could make your code much more readable by being more concise.

Here's what your code might look like if you took this advice (I'm making some assumptions of your source data):

for(NSObject *obj in resultArray){
    APParameters *parItem = [[APParameters alloc] init];

    parItem.parameterName = obj[@"PAR_VPARAM"];
    parItem.parameterValue = obj[@"PAR_VALUE"];

    // To capture the IDI property, you will either have to
    // define a new IDI class with a property named "IDI_ID",
    // live with NSDictionary, or add a property to your
    // Parameters class which holds the IDI_ID value directly.

    // In this example, I grabbed the IDI_ID value directly.
    parItem.itemID = obj[@"IDI"][@"IDI_ID"];
}
Sign up to request clarification or add additional context in comments.

4 Comments

I find the best way to create a new object from JSON is to code an initWithDictionary method for the class that accepts the JSON dictionary.
@HotLicks I personally like to create a class method like +[APThing thingWithDictionary:], but it's effectively the same thing (especially with ARC).
Yeah, they're pretty much equivalent. Especially if you have nested dictionaries creating nested objects, it's very natural to do it this (either) way, so that you have a standardized mechanism and style. Gives you the benefits of a Jackson-ish implementation but without having to insert mysterious markup or code arcane rules.
Thanks! about the code, i just used a json sample of the internet.
0

First of all, I'd suggest you to cast JSON data to an NSArray instead of NSMutableArray if you're not going to add or remove new objects to the array.

About "IDI" indices, they are not being parsed as strings like other indices since they're dictionaries. You also should create Parameters object manually instead of casting directly.

An example:

// In Parameters.h
@property (nonatomic, strong) NSString *PAR_VPARAM;
@property (nonatomic, strong) NSDictionary *IDI;

Then after parsing JSON,

for (NSDictionary *obj in resultArray){
     Parameters *paritem = [[Parameters alloc] init];
     paritem.PAR_VPARAM = [obj valueForKey:@"PAR_VPARAM"];
     paritem.IDI = [obj valueForKey:@"IDI"];
     int test = (int)[paritem.IDI valueForKey:@"IDI_ID"];
}

This should work well and you can create new properties for other JSON indices.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.