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?

Siddharthan Asokan
  • 4,321
  • 11
  • 44
  • 80

4 Answers4

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];
}
Serluca
  • 2,102
  • 2
  • 19
  • 31
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?

Pascal
  • 16,846
  • 4
  • 60
  • 69
  • It should be done dynamically. Accessing the object's object (which could be a dictionary) – Siddharthan Asokan Nov 05 '13 at 02:44
  • 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. – Pascal Nov 06 '13 at 02:13
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.

ryan cumley
  • 1,901
  • 14
  • 11
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"];
Sam Fischer
  • 1,442
  • 19
  • 35
  • 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. – Siddharthan Asokan Oct 27 '13 at 04:13
  • 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. – Sam Fischer Oct 27 '13 at 04:15
  • But does it apply for the way I input object and keys? – Siddharthan Asokan Oct 27 '13 at 04:36
  • Since querybuild is the `NSMutableDictionary` object - of course you can! That'll be elementary once you get the JSON data in `NSDictionary` format. – Sam Fischer Oct 27 '13 at 04:41
  • The whole point of the question is how to build a NSMutableDictionary data by looping and condition so I can convert into a JSON string – Siddharthan Asokan Oct 27 '13 at 04:46
  • 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". – Sam Fischer Oct 27 '13 at 05:46
  • 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. – Sam Fischer Oct 27 '13 at 05:51