Complex Json Data and NSMutableDictionary parsing issue - iphone

Hi I'm using SBJson for moving Json data in and out of NSMutableDictionar, Im Building the main NSMutableDictionary from few others NSMutableDictionary like this
- (NSMutableDictionary *) getGeneral{
NSMutableDictionary *pType = [[NSMutableDictionary alloc]init];
[pType setObject:[NSNumber numberWithInteger:3] forKey:#"Ptype"];
NSMutableDictionary *session = [[NSMutableDictionary alloc]init];
[session setObject:[NSNumber numberWithInteger:-1] forKey:#"user_id"];
[session setObject:#"3" forKey:#"device_token"];
[session setObject:[NSNumber numberWithInteger:-1] forKey:#"customer_id"];
[session setObject:#"3" forKey:#"client_time"];
NSMutableDictionary *Error = [[NSMutableDictionary alloc]init];
[Error setObject:[NSNumber numberWithInteger:-1] forKey:#"error_code"];
[Error setObject:#"3" forKey:#"error_message"];
NSMutableDictionary *Successful = [[NSMutableDictionary alloc]init];
[Successful setObject:[NSNumber numberWithInteger:-1] forKey:#"success_code"];
[Successful setObject:#"3" forKey:#"success_message"];
NSMutableDictionary *Details = [[NSMutableDictionary alloc]init];
[Details setObject:#"3" forKey:#"user_name" ];
[Details setObject:#"3" forKey:#"user_password" ];
[Details setObject:[NSNumber numberWithInteger:-1] forKey:#"StartCallID"];
[Details setObject:#"3" forKey:#"StartDate" ];
[Details setObject:#"3" forKey:#"EndDate"];
NSMutableDictionary *General = [[NSMutableDictionary alloc]init];
[General setObject:pType forKey:#"Ptype"];
[General setObject:session forKey:#"Session"];
[General setObject:Error forKey:#"Error"];
[General setObject:Successful forKey:#"Successful"];
[General setObject:Details forKey:#"Details"];
return General;
}
and then i assign data into it i expected to get this Json structure:
{
"Ptype":[{"Ptype":-1}],
"Session":[{
"user_id":-1,
"device_token":" ",
"customer_id":-1,
"client_time":"",
}],
"Error":[{"error_code":-1,
"error_message":""}],
"Successful":[{"success_code":-1,
"success_message":""}],
"Details":[{
"user_name":" ",
"user_password":" ",
"StartCallID":-1,
"StartDate":" ",
"EndDate":" "
}]}
but there is no "]" or "[" in my json it looks like this, the order also change but this is not a problem, i take care of it on the server, issue is no square brackets
{"Session":
{"customer_id":-1,
"client_time":"3",
"user_id":-1,
"device_token":"3"},
"Error":{"error_code":-1,"error_message":"3"},
"Successful":{"success_code":-1,"success_message":"3"},
"Details":{"StartCallID":-1,
"user_password":"gg",
"user_name":"ff",
"StartDate":"3",
"EndDate":"3"},
"Ptype":{"Ptype":3}}
any one know on this issue, i need multiple items with the same name and this is the json standart for it
Thanks

Square brackets surrounds an array and you only have dictionaries.
The key is unique within each dictionary.
For example to put customer_id in a dictionary within an array:
NSArray *myArray = [NSArray arrayWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:
#"-1",
#"customer_id",
nil] nil];
Link of interest Understand JSON 3min lesson

Related

creating JSON format in Objective C

For an application i want to create a JSON in format as mentioned below,
"Students" : {
"results": {
"Grade1": {
"studentresult": "pass",
"marksheet": "provided"
},
"ID": 01,
"Name": "Student1",
}
}
I am using the following code to create the same,
NSMutableDictionary *gradedetails = [[NSMutableDictionary alloc] init];
[gradedetails setObject:#"pass" forKey:#"studentresult"];
[gradedetails setObject:#"provided" forKey:#"marksheet"];
NSMutableDictionary *sdetails = [[NSMutableDictionary alloc] init];
[sdetails setObject:#"01" forKey:#"ID"];
[sdetails setObject:#"Name" forKey:#"Student1"];
NSMutableDictionary *grade = [[NSMutableDictionary alloc] init];
[grade setObject:gradedetails forKey:#"Grade1"];
NSMutableArray *rarray = [[NSMutableArray alloc] init];
[rarray addObject:grade];
[rarray addObject:sdetails];
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
[results setObject:rarray forKey:#"results"];
NSMutableDictionary *stud = [[NSMutableDictionary alloc] init];
[stud setObject:rdic forKey:#"Students"];
NSData *jsondata = [NSJSONSerialization dataWithJSONObject:stud options:NSJSONWritingPrettyPrinted error:&error];
I am getting in the following format,
"Students" : {
"results" : [
{
"Grade1" : {
"studentresult" : "pass",
"marksheet" : "provided"
}
},
{
"ID" : "01",
"Name" : "Student1"
}
]
}
}
could someone please help me in creating the format.
Thanks.
Required Data , You can get this way . Just convert that stud dict in JSon or any other format you want. Remove that array , You don't need it , As you mentioned it in the required format.
NSMutableDictionary *gradedetails = [[NSMutableDictionary alloc] init];
[gradedetails setObject:#"pass" forKey:#"studentresult"];
[gradedetails setObject:#"provided" forKey:#"marksheet"];
NSMutableDictionary *sdetails = [[NSMutableDictionary alloc] init];
[sdetails setObject:#"01" forKey:#"ID"];
[sdetails setObject:#"Name" forKey:#"Student1"];
[sdetails setObject:gradedetails forKey:#"Grade1"];
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
[results setObject:sdetails forKey:#"results"];
NSMutableDictionary *stud = [[NSMutableDictionary alloc] init];
[stud setObject:results forKey:#"Students"];
NSLog(#"Required Format Data is %#",stud);
Depends on your code:
NSMutableDictionary *gradedetails = [[NSMutableDictionary alloc] init];
[gradedetails setObject:#"pass" forKey:#"studentresult"];
[gradedetails setObject:#"provided" forKey:#"marksheet"];
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
[results setObject:gradedetails forKey:#"Grade1"];
[results setObject:#"01" forKey:#"ID"];
[results setObject:#"Name" forKey:#"Student1"];
NSMutableDictionary *stud = [[NSMutableDictionary alloc] init];
[stud setObject:results forKey:#"Students"];
NSDictionary *gradedetails = #{#"studentresult" : #"pass", #"marksheet" : #"provided"};
NSDictionary *grade = #{ #"Grade1" : gradedetails}
NSDictionary *sdetails = #{#"ID" : #"01", #"Student1" : #"Name"};
NSArray *resultsArray = #[grade, sdetails];
NSDictionary *results= #{#"results" : resultsArray};
NSDictionary *stud = #{#"Students" : results};
NSData *jsondata = [NSJSONSerialization dataWithJSONObject:stud options:NSJSONWritingPrettyPrinted error:&error];
I wonder why few developper use this notation
check this code-
NSMutableDictionary *students=[NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
for (NSDictionary *dictionofstudents in students)
{
NSMutableDictionary *results=[dictionofstudents objectForKey:#"results"];
for (NSDictionary *dictionofresults in results)
{
NSMutableDictionary *grade1=[dictionofresults objectForKey:#"Grade1"];
for (NSDictionary *dictionofgrade1 in grade1)
{
NSString *studentresult=[dictionofgrade1 objectForKey:#"studentresult"];
NSString *marksheet=[dictionofgrade1 objectForKey:#"marksheet"];
[arrayofstudentresult addObject:studentresult];
[arrayofmarksheet addObject:marksheet];
}
NSString *ID=[dictionofresults objectForKey:#"ID"];
NSString *name=[dictionofresults objectForKey:#"Name"];
[arrayofID addObject:ID];
[arrayofname addObject:name];
}
}
In order to get the format you want out of it, you have to pack information in that particular format.
Your problem is right about here:
NSMutableArray *rarray = [[NSMutableArray alloc] init];
[rarray addObject:grade];
[rarray addObject:sdetails];
The desired format has no arrays, so why are you creating an array?
A hint for you:
You should be creating exactly 4 dictionaries, and no arrays.
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
NSMutableDictionary *grade = [[NSMutableDictionary alloc] init];
[grade setValue:#"pass" forKey:#"studentresult"];
[grade setValue:#"provided" forKey:#"marksheet"];
[result setValue:grade forKey:#"Grade1"];
[result setValue:#"01" forKey:#"ID"];
[result setValue:#"Student1" forKey:#"Name"];
[dict setValue:result forKey:#"results"];
NSMutableDictionary *stdnt = [[NSMutableDictionary alloc] init];
[stdnt setValue:dict forKey:#"Students"];
NSError *error = nil;
NSData *jsondata = [NSJSONSerialization dataWithJSONObject:stdnt options:NSJSONWritingPrettyPrinted error:&error];
NSString *s = [[NSString alloc] initWithData:jsondata encoding:NSUTF8StringEncoding];
NSLog(#"%#",s);
It may helps you.

exc_breakpoint while JSON parsing

I want to parse many JSON strings. Here is the code:
while(stations.count > 0) {
NSString*string = [[[NSString alloc] initWithString:[stations objectAtIndex:0]] retain];
NSMutableDictionary*dic = [[[NSMutableDictionary alloc]init]retain];
NSData*data = [[[NSData alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]]retain];
NSMutableDictionary* pars = [[NSMutableDictionary alloc]initWithDictionary:[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]];
[dic setObject:[NSString stringWithString:[pars objectForKey:#"nm"]] forKey:#"nm"];
[dic setObject:[NSString stringWithString:[pars objectForKey:#"btr"]] forKey:#"btr"];
[dic setObject:[NSString stringWithString:[pars objectForKey:#"id"]] forKey:#"id"];
[dic setObject:[NSString stringWithString:[pars objectForKey:#"cntr"]] forKey:#"cntr"];
[dic setObject:[NSString stringWithString:[pars objectForKey:#"gnr"]] forKey:#"gnr"];
[pars release];
#try {
[parsedData addObject:[NSDictionary dictionaryWithDictionary:dic]];
}
#catch (NSException* exc) {
NSLog(#"%#, %#", exc.description, exc.reason);
}
[dic release];
[data release];
[string release];
[stations removeObjectAtIndex:0];
if (i%1000==0) {
NSLog(#"nnnn %i %i", parsedData.count, stations.count);
}
i++;
float k = count;
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
}
On adding (usually but not every time) string to array I get error:
exc_breakpoint (code=exc_i386_bpt
and:
GuardMalloc[Radiocent new try-1820]: Failed to VM allocate 68752 bytes
GuardMalloc[Radiocent new try-1820]: Explicitly trapping into debugger!!!
Stations array is pretty big... about 60000 strings.
First of all when you alloc you don't need to retain as retain count is already +1.
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
Not
NSMutableDictionary*dic = [[[NSMutableDictionary alloc]init]retain];
Below line already returs mutable dictionary so you don't have to create a new dictionary out of that and if you want to change then just call a - mutableCopy on it.
NSMutableDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
or to create a copy:
NSMutableDictionary *dictionary = [[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil] mutableCopy];
If stations is JSON string then for all stations do this:
NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
NSArray *stationsArray = [[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil] mutableCopy];
for (NSDictionary *stationDic in stationArray)
{
// This will iterate over each station dictionary in the station array
// Do your stuff here ...
}
For your example: (I have added \" to escape the double quotes, you don't have to)
Placed square brackets around your example this make it an array and you can iterate through each using the given code below. (Add only if they are not there)
NSString *example = #"[{\"id\":\"02AB99\",\"btr\":\"24\",\"cntr\":\"461E\",\"gnr\":\"8A51\",\"nm\":\"88.3 Fm Radio Q Jogjakarta\"}, {\"id\":\"026058\",\"btr\":\"160\",\"cntr\":\"461E\",\"gnr\":\"8A7B\",\"nm\":\"88.3 The Dog\"}, {\"id\":\"0300D2\",\"btr\":\"55 64\",\"cntr\":\"461C\",\"gnr\":\"8A75\",\"nm\":\"88.3 The Wind\"}, {\"id\":\"0159E6\",\"btr\":\"128\",\"cntr\":\"4610\",\"gnr\":\"8A6C\",\"nm\":\"88.30 Z Fm Radio Word Online\"}]";
NSError *error = nil;
NSArray *stationArray = [NSJSONSerialization JSONObjectWithData:[example dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
if (!error)
{
for (NSDictionary *stationDic in stationArray)
{
NSLog(#"\nName: %# \nDump: \n%#", [stationDic valueForKey:#"nm"], stationDic);
}
}

Using a nested NSMutableDictionary

simple question, I need to structure data in the following format:
UserID:
1 {
Name = Bob
Surname = Hope
}
2 {
...
I can used an NSMutableDictionary to add a single layer with keys, but I am unable to create a child associate with a certain key.
I have tried creating a mutable dictionary and assigning that to a key:
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
NSArray *keys = [[NSArray alloc] initWithObjects:#"Name", #"Surname", nil];
NSArray *details = [[NSArray alloc] initWithObjects:#"Bob",#"Hope", nil];
NSDictionary *person = [[NSMutableDictionary alloc] initWithObjects:details forKeys:keys];
[dic setValue:#"1" forKey:#"id"];
[[dic objectForKey:#"id"] setDictionary: person];
I think it is better to use an array of dictionaries, each dictionary representing a user.
NSMutableArray *users= [[NSMutableArray alloc] init];
NSArray *keys = [[NSArray alloc] initWithObjects:#"Name", #"Surname", nil];
NSArray *details = [[NSArray alloc] initWithObjects:#"Bob",#"Hope", nil];
NSDictionary *person = [[NSMutableDictionary alloc] initWithObjects:details forKeys:keys];
[users addObject:person];
u can also set the objects for dictionary in this way
[dic setObject:person forKey:#"id"];

iphone: problem in NSMutableArray and NSMutableDictionary

Dont know whats wrong with this array
NSMutableArray *locations=[[NSMutableArray alloc] init];
NSMutableDictionary *aLocation=[[NSMutableDictionary alloc] init];
[aLocation setObject:#"26.8465108" forKey:#"lat"];
[aLocation setObject:#"80.9466832" forKey:#"long"];
[locations addObject:aLocation];
[aLocation removeAllObjects]
[aLocation setObject:#"26.846127990018164" forKey:#"lat"];
[aLocation setObject:#"80.97541809082031" forKey:#"long"];
[locations addObject:aLocation];
[aLocation removeAllObjects];
but every time I remove all objects from aLocations dictionary those values get deleted from locations array as well.
Please help me in this
This behaviour is correct and you can't reuse NSMutableDictionary as you do: NSMutableArray does not copy objects it contains - it just stores pointers to those objects. So if an object you added to array changes then array has pointer to that changed object.
To fix your code create NSMutableDictionary instance each time you need to add it to array (or create immutable dictionary if you actually don't need mutable object):
NSMutableArray *locations=[[NSMutableArray alloc] init];
NSMutableDictionary *aLocation= [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"26.8465108", #"lat",#"80.9466832" ,#"long", nil ];
[locations addObject:aLocation];
aLocation= [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"26.846127990018164", #"lat",#"80.97541809082031" ,#"long", nil ];
[locations addObject:aLocation];
NSMutableArray *locations=[[NSMutableArray alloc] init];
NSMutableDictionary *aLocation=[[NSMutableDictionary alloc] init];
[aLocation setObject:#"26.8465108" forKey:#"lat"];
[aLocation setObject:#"80.9466832" forKey:#"long"];
[locations addObject:aLocation];
[aLocation release];
NSMutableDictionary *aLocation1=[[NSMutableDictionary alloc] init];
[aLocation1 setObject:#"26.846127990018164" forKey:#"lat"];
[aLocation1 setObject:#"80.97541809082031" forKey:#"long"];
[locations addObject:aLocation1];
[aLocation1 release];
NSMutableArray *locations=[[NSMutableArray alloc] init];
NSMutableDictionary *aLocation= [NSMutableDictionary initWithObjectsAndKeys:
#"26.8465108", #"lat",#"80.9466832" ,#"long", nil ];
[locations addObject:aLocation];
aLocation= [NSMutableDictionary initWithObjectsAndKeys:
#"26.846127990018164", #"lat",#"80.97541809082031" ,#"long", nil ];
[locations addObject:aLocation];

How can we store into an NSDictionary? What is the difference between NSDictionary and NSMutableDictionary?

I am developing an application in which I want to use an NSDictionary. Can anyone please send me a sample code explaining the procedure how to use an NSDictionary to store Data with a perfect example?
The NSDictionary and NSMutableDictionary docs are probably your best bet. They even have some great examples on how to do various things, like...
...create an NSDictionary
NSArray *keys = [NSArray arrayWithObjects:#"key1", #"key2", nil];
NSArray *objects = [NSArray arrayWithObjects:#"value1", #"value2", nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects
forKeys:keys];
...iterate over it
for (id key in dictionary) {
NSLog(#"key: %#, value: %#", key, [dictionary objectForKey:key]);
}
...make it mutable
NSMutableDictionary *mutableDict = [dictionary mutableCopy];
Note: historic version before 2010: [[dictionary mutableCopy] autorelease]
...and alter it
[mutableDict setObject:#"value3" forKey:#"key3"];
...then store it to a file
[mutableDict writeToFile:#"path/to/file" atomically:YES];
...and read it back again
NSMutableDictionary *anotherDict = [NSMutableDictionary dictionaryWithContentsOfFile:#"path/to/file"];
...read a value
NSString *x = [anotherDict objectForKey:#"key1"];
...check if a key exists
if ( [anotherDict objectForKey:#"key999"] == nil ) NSLog(#"that key is not there");
...use scary futuristic syntax
From 2014 you can actually just type dict[#"key"] rather than [dict objectForKey:#"key"]
NSDictionary *dict = [NSDictionary dictionaryWithObject: #"String" forKey: #"Test"];
NSMutableDictionary *anotherDict = [NSMutableDictionary dictionary];
[anotherDict setObject: dict forKey: "sub-dictionary-key"];
[anotherDict setObject: #"Another String" forKey: #"another test"];
NSLog(#"Dictionary: %#, Mutable Dictionary: %#", dict, anotherDict);
// now we can save these to a file
NSString *savePath = [#"~/Documents/Saved.data" stringByExpandingTildeInPath];
[anotherDict writeToFile: savePath atomically: YES];
//and restore them
NSMutableDictionary *restored = [NSDictionary dictionaryWithContentsOfFile: savePath];
The key difference: NSMutableDictionary can be modified in place, NSDictionary cannot. This is true for all the other NSMutable* classes in Cocoa. NSMutableDictionary is a subclass of NSDictionary, so everything you can do with NSDictionary you can do with both. However, NSMutableDictionary also adds complementary methods to modify things in place, such as the method setObject:forKey:.
You can convert between the two like this:
NSMutableDictionary *mutable = [[dict mutableCopy] autorelease];
NSDictionary *dict = [[mutable copy] autorelease];
Presumably you want to store data by writing it to a file. NSDictionary has a method to do this (which also works with NSMutableDictionary):
BOOL success = [dict writeToFile:#"/file/path" atomically:YES];
To read a dictionary from a file, there's a corresponding method:
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:#"/file/path"];
If you want to read the file as an NSMutableDictionary, simply use:
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:#"/file/path"];