Creating nested JSON string using nsmutabledictionary
Asked Answered
B

4

10

I'm trying to create a json string of the below format:

{
  "cat_id" : 4992, 
  "brand"  : "Toshiba",
  "weight" : { "gte":1000000, "lt":1500000 },
  "sitedetails" : {
      "name" : "newegg.com",
      "latestoffers" : {
          "currency": "USD",
          "price"   : { "gte" : 100 } 
     }
 }
}

I used the following method to generate this:

-(void)queryBuilderWithObj:(NSString *)object andKeyValue:(NSString *)key{
NSLog(@"object %@ and key %@",object,key);


if([key rangeOfString:@","].location == NSNotFound){
    [querybuild setObject:object forKey:key];
}else{
    NSArray *tempArray = [key componentsSeparatedByString:@","];
    int index = tempArray.count - 1;
    NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
    while (index) {
        if (index == tempArray.count - 1) {
            if([querybuild objectForKey:[tempArray objectAtIndex:index]]){
                NSMutableArray *objArray = [[NSMutableArray alloc] init];
                [objArray addObject:[querybuild objectForKey:[tempArray objectAtIndex:index]]];
                [objArray addObject:object];
                [tempDict setObject:objArray forKey:[tempArray objectAtIndex:index]];


            }else{
                [tempDict setObject:object forKey:[tempArray objectAtIndex:index]];
            }

        }else{
            if([querybuild objectForKey:[tempArray objectAtIndex:index]]){

                NSMutableArray *objArray = [[NSMutableArray alloc] init];
                [objArray addObject:[querybuild objectForKey:[tempArray objectAtIndex:index]]];

                NSMutableDictionary *subDict = [[NSMutableDictionary alloc] init];
                [subDict setDictionary:tempDict];

                [objArray addObject:subDict];
                [tempDict setObject:objArray forKey:[tempArray objectAtIndex:index]];



            }else{
                NSMutableDictionary *subDict = [[NSMutableDictionary alloc] init];
                [subDict setDictionary:tempDict];
                [tempDict setObject:subDict forKey:[tempArray objectAtIndex:index]];
            }
        }
        index --;
    }



    [querybuild setObject:tempDict forKey:[tempArray objectAtIndex:0]];

}
NSLog(@"querybuild %@ ",querybuild);


}

and the final nsmutabledictionary generated is:

 querybuild {
brand = Toshiba;
"cat_id" = 4992;
sitedetails =     {
    gte = 100;
    latestoffers =         {
        gte = 100;
        price =             {
            gte = 100;
        };
    };
    price =         {
        gte = 100;
    };
};
weight =     {
    lt = 1500000;
};

}

I passed the object and key as below:

[sem queryBuilderWithObj:@"4992" andKeyValue:@"cat_id" ];
[sem queryBuilderWithObj:@"Toshiba" andKeyValue:@"brand"];
[sem queryBuilderWithObj:@"1000000" andKeyValue:@"weight,gte"];
[sem queryBuilderWithObj:@"1500000" andKeyValue:@"weight,lt"];
[sem queryBuilderWithObj:@"newegg.com"andKeyValue:@"sitedetails,name" ];
[sem queryBuilderWithObj:@"USD" andKeyValue:@"sitedetails,latestoffers,currency"];
[sem queryBuilderWithObj:@"100" andKeyValue:@"sitedetails,latestoffers,price,gte"];

Any idea on how to generate the required output? querybuild is the nsmutabledictionary object in this method declared as a class variable?

Bruce answered 27/10, 2013 at 3:47 Comment(0)
A
12

If you want this the best way is create more dictionary example:

NSMutableDictionary *json= [[NSMutableDictionary alloc] init];
[json setObject:@"4992" forKey:@"cat_id"];
[json setObject:@"Toshiba" forKey:@"brand"];
//create weight object
NSMutableDictionary *weight= [[NSMutableDictionary alloc] init];
[weight setObject:@"1000000" forKey:@"gte"];
[weight setObject:@"1500000" forKey:@"lt"];
//attach the object
[json setObject:weight forKey:@"weight"];
//create sitedetails objects
NSMutableDictionary *sitedetails= [[NSMutableDictionary alloc] init];
[sitedetails setObject:@"newegg.com" forKey:@"name"];
//create latestoffers objects
NSMutableDictionary *latestoffers= [[NSMutableDictionary alloc] init];
[latestoffers setObject:@"USD" forKey:@"currency"];
//new dictionary for price
[sitedetails setObject:latestoffers forKey:@"latestoffers"];
[json setObject:sitedetails forKey:@"sitedetails"];
NSLog(@"%@",json);

After you can convert dictionary in json string...

-(NSString*)getJsonStringByDictionary:(NSDictionary*)dictionary{
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary
                                                   options:NSJSONWritingPrettyPrinted
                                                     error:&error];
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
Athalia answered 29/10, 2013 at 10:47 Comment(1)
can the dictionary generated more simply?Madrid
M
7

Using the new Objective-C syntax and NSJSONSerialization, as pointed out by others, this can be done quite nicely:

NSDictionary *latestprice = @{@"gte": @100};
NSDictionary *latest = @{@"currency": @"USD", @"price": latestprice};
NSDictionary *details = @{@"name": @"newegg.com", @"latestoffers": latest};
NSDictionary *weight = @{@"gte": @1000000, @"lt": @1500000};
NSDictionary *json = @{
    @"cat_id": @4992,
    @"brand": @"Toshiba",
    @"weight": weight,
    @"sitedetails": details
};


NSData *data = [NSJSONSerialization dataWithJSONObject:json
                                               options:NSJSONWritingPrettyPrinted
                                                 error:nil];
NSString *jsonStr = [[NSString alloc] initWithData:data
                                          encoding:NSUTF8StringEncoding];

I don't know what your querybuild is, but if it is a dictionary you can just pull out the data as needed. Or do you need to dynamically create this structure, based on the keys in querybuild?

Mancy answered 4/11, 2013 at 22:18 Comment(2)
It should be done dynamically. Accessing the object's object (which could be a dictionary)Bruce
In that case you're on the right track, just create a NSMutableDictionary and stick the values in there after splitting the keys at the commas, recursively creating more dictionaries as you encounter commas in keys.Mancy
R
2

Have you tried playing with the JSONObjectWithData:options:error: of the NSJSONSerialization class?

it also features a handy isValidJSONObject method that you can use to help you debug the structure you're trying to convert.

Ratliff answered 27/10, 2013 at 3:58 Comment(0)
G
0

No need for that. Just use the in-built NSJSONSerialization because that's what its for. It puts JSON objects in NSDictionaries or NSArrays.

Here's how you go about using it :

//This part is just to download the data. If you're using another method - that's fine. Just make sure that the download is in NSData format
    NSURL *url = [[NSURL alloc] initWithString : @"YOUR_URL_HERE"];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL : url];
    NSData *jsonData = [NSURLConnection sendSynchronousRequest:request
                                             returningResponse:nil
                                                         error:nil];
//This is the actual NSJSONSerialization part.
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData
                                                             options:NSJSONReadingMutableLeaves
                                                               error:nil];

Now you can access the elements from the NSDictionary like this :

NSString *cat_id = [jsonDict objectForKey : @"cat_id"];

And those objects in { } are NSDictionaries - nested ones. They can be accessed like :

NSDictionary *slidedetailsDict = [jsonDict objectForKey : @"slidedetails"];
NSString *name = [slidedetailsDict objectForKey : @"name"];
Guiscard answered 27/10, 2013 at 4:6 Comment(7)
Do u understand the question? I'm trying to create a JSON string of that specific pattern? Its not about creating any JSON string or accessing the object.Bruce
I understand. But the point is that NSJSONSerialization is the best option here. If you want to create custom objects, create a custom class and set its properties to the various parts of the JSON data.Guiscard
But does it apply for the way I input object and keys?Bruce
Since querybuild is the NSMutableDictionary object - of course you can! That'll be elementary once you get the JSON data in NSDictionary format.Guiscard
The whole point of the question is how to build a NSMutableDictionary data by looping and condition so I can convert into a JSON stringBruce
The logic is so simple. Whenever a new piece of data is downloaded - Add an custom object which'll have the data (via NSJSONSerialization) to an NSMutableArray. It'll have all the separate objects stored and you can call then by "looping and condition".Guiscard
If you don't want to store it in a NSMutableArray, you can add it to a NSMutableDictionary just that you'll to specify a different key every time.Guiscard

© 2022 - 2024 — McMap. All rights reserved.