i have this data structure :
{
"artistlist " : [
{
"performer" : "Gate Zero"
},
{
"performer" : "nightech"
},
{
"performer" : "Marko Fuerstenberg"
},
]
}
I read this structure from NSString into NSDictionary with this line of code:
JSON = [NSJSONSerialization JSONObjectWithData:
[[chunks objectAtIndex:1]
dataUsingEncoding:NSUTF8StringEncoding] options:
NSJSONReadingMutableContainers error: &e];
with: [JSON objectForKey:#"artistlist "] i get this structure:
(
{
performer = "Gate Zero";
},
{
performer = nightech;
},
{
performer = "Marko Fuerstenberg";
}
)
Is there any way to go "deeper" ?
how would i parse the resulting Structure ?
I would like to get a list of values or access performer names directly. What if i have several values in a tupel for example performer name, album, year. How would i access those values?
Thank you.
Yes, after you have [JSON objectForKey:#"artistlist "], you get an NSArray of NSDictionaries (slightly confusing!).
NSArray *performersArray = [JSON objectForKey:#"artistlist"];
for (NSDictionary *performerDic in performersArray) {
NSLog(#"%#", [performerDic objectForKey:#"performer"]);
}
This should yield each performer name. Alternatively, you can do for (NSUInteger i = 0; i < [performersArray count]; i++) and access NSDictionary *performersDic = [performersArray objectAtIndex: i]. From there, you can similarly use [performsDic objectForKey:#"performer"]
Like this:
[[[JSON objectForKey:#"artistlist "] objectAtIndex: 1] objectForKey:#"performer"]
It will give you "nightech".
{} corresponds to NSDictionary, [] corresponds to NSArray.
You'll have to use recursion. For example, assuming you have only nested NSDictionaries (easy to modify to work with NSArrays):
- (void) getArtistFromJsonObject:(NSDictionary *)obj {
for (NSString *key in [obj allKeys]) {
id child = [obj objectForKey:key];
if ([child isKindOfClass:[NSString class]]) {
// that's the actual string
// NSLog(#"Found artist: %#", child); // or do whatever needed
} else if ([child isKindOfClass:[NSDictionary class]]) {
[self getArtistFromJsonObject:child];
}
}
}
Related
I have a problem with fetching data from Json response.
Here is an example data structure :
(
{
AT = "<null>";
DId = 0;
DO = 0;
PLId = 33997;
PdCatList = (
{
PLId = 33997;
PPCId = 0;
pdList = (
{
IsDis = 0;
IsPS = 0;
IsT = 1;
PA = 1;
PCId = 119777;
}
);
}
);
PdId = 0;
SId = 0;
Sec = 1;
},
{
AT = "<null>";
DId = 0;
DO = 11;
Dis = 0;
PLId = 34006;
PdCatList = (
{
PLId = 34006;
PPCId = 0;
pdList = (
{
IsDis = 0;
IsPS = 0;
IsT = 1;
PA = 1;
PCId = 119830;
},
{
IsDis = 0;
IsPS = 0;
IsT = 1;
PA = 1;
PCId = 119777;
}
);
},
{
PLId = 33997;
PPCId = 0;
pdList = (
{
IsDis = 0;
IsPS = 0;
IsT = 1;
PA = 1;
PCId = 119777;
}
);
}
);
PdId = 0;
SId = 0;
Sec = 1;
},
)
how would i parse the resulting Structure ?
I would like to get a list of values directly. What if i have several values in a tupel for example performer PdCatList, pdList. How would i access those values?
Can anyone help me
Thank's
my code is
NSError *error;
Array1 = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
for(int i=0;i<[Array1 count];i++)
{
NSDictionary *dict1 = [Array1 objectAtIndex:i];
NSLog(#"Array1.....%#",dict1);
Array2=[dict1 valueForKey:#"PdCatList"];
for(int i=0;i<[Array2 count];i++)
{
NSDictionary *dict2 = [Array2 objectAtIndex:i];
NSLog(#"Array2.....%#",dict2);
Array3=[dict2 valueForKey:#"pdList"];
for(int i=0;i<[Array3 count];i++)
{
NSDictionary *dict3 = [Array3 objectAtIndex:i];
NSLog(#"Array3.....%#",dict3);
}
}
}
Try this...
NSError *error;
Array1 = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
for(int i=0;i<[Array1 count];i++)
{
NSDictionary *dict1 = [Array1 objectAtIndex:i];
ATArray =[dict1 valueForKey:#"AT"];
DIdArray =[dict1 valueForKey:#"DId"];
DOArray =[dict1 valueForKey:#"DO"];
PLIdArray =[dict1 valueForKey:#"PLId"];
etc...
Array2=[dict1 valueForKey:#"PdCatList"];
for(int i=0;i<[Array2 count];i++)
{
NSDictionary *dict2 = [Array2 objectAtIndex:i];
PLIdArray =[dict2 valueForKey:#"PLId"];
PPCIdArray =[dict2 valueForKey:#"PPCId"];
etc…
Array3=[dict2 valueForKey:#"pdList"];
for(int i=0;i<[Array3 count];i++)
{
NSDictionary *dict3 = [Array3 objectAtIndex:i];
IsDisArray =[dict3 valueForKey:#"IsDis"];
IsPSArray =[dict3 valueForKey:#"IsPS"];
IsTArray =[dict3 valueForKey:#"IsT"];
PAArray =[dict3 valueForKey:#"PA"];
PCIdArray =[dict3 valueForKey:#"PCId"];
}
}
}
I think what you require here is to understand what a JSON response is rather than the Answer to get the values of some objects from your JSON response.
If you want some detail explanation about JSON Parsing then you can take a look at NSJSONSerialization Class Reference. Everything is given there or you can take a look at my Answer.
Understand the Concept. It depends on what you have inside your JSON. If it's an Array ( Values inside [ ]) then you have to save in NSArray, if it's a Dictionary ( Values inside { }) then save as NSDictionary and if you have single values like string , integer, double then you have to save them using appropriate Objective-C Data types.
For some simple details with example , you can check my Answer from this question.
Use JSONKit(https://github.com/johnezang/JSONKit):
NSString *yourJSONString = ...
NSArray *responseArray = [yourJSONString objectFromJSONString];
for(NSDictionary *responseDictionary in responseArray)
{
NSString *atString = [responseDictionary objectForKey:#"AT"];
...
NSArray *pdCatListArray = [responseDictionary objectForKey:#"PdCatList"];
...here you can get all values you want,if you want to get more details in PdCatList,use for in pdCatListArray ,you can do what you want.
}
Use following method:
NSDictionary *mainDict;
SBJSON *jsonParser = [[SBJSON alloc]init];
if([[jsonParser objectWithString:responseString] isKindOfClass:[NSDictionary class]])
{
mainDict=[[NSDictionary alloc]initWithDictionary:[jsonParser objectWithString:responseString]];
}
NSDictionary *firstDict=[NSDictionary alloc]initWithDictionary:[mainDict valueForKey:#""];
You have to add JSON framework which is parse string into NSDictionary.
Use zip file from here
Open Folder and rename Classes folder to "JSON".
Copy JSON Folder and include in your project.
Import header file like below in controller where you want to parse JSON String.
#import "SBJSON.h"
#import "NSString+SBJSON.h"
Now, Parse your response string in to NSDictionary like below.
NSMutableDictionary *dictResponse = [strResponse JSONValue];
You can use KVC
to access the nested properties in the JSON. You need to know about KVC and dot syntax and Collection operators
Frameworks that map JSON to objects, such as RestKit rely heavily on KVC.
Following your sample, you could get a list of all PdCatList objects:
//sample data
NSArray *json = #[
#{#"PLId" : #33997,
#"PdCatList" : #{#"PLId": #33998,
#"PPCId" : #1,
#"pdList" : #{
#"PCId" : #119777
}}
},
#{#"PLId" : #33999,
#"PdCatList" : #{#"PLId": #4444,
#"PPCId" : #0,
#"pdList" : #{
#"PCId" : #7777
}}}
];
//KVC
NSArray *pdCatLists = [json valueForKeyPath:#"#unionOfObjects.PdCatList"];
With this you can, for example, make a very basic object mapping (which does not take care of relationships)
In PdCatList.h
#interface PdCatList : NSObject
#property (readonly, strong, nonatomic) NSNumber *PLId;
#property (readonly, strong, nonatomic) NSNumber *PPCId;
+ (instancetype)listWithDictionary:(NSDictionary *)aDictionary;
#end
In PdCatList.m
#implementation PdCatList
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
#try {
[super setValue:value forUndefinedKey:key];
}
#catch (NSException *exception) {
NSLog(#"error setting undefined key: %#, exception: %#", key, exception);
};
}
+ (id)listWithDictionary:(NSDictionary *)aDictionary
{
PdCatList *result = [[self alloc] init];
[result setValuesForKeysWithDictionary:aDictionary];
return result;
}
#end
After getting the json object
NSArray *pdCatLists = [json valueForKeyPath:#"#unionOfObjects.PdCatList"];
[pdCatLists enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PdCatList *each = [PdCatList listWithDictionary:obj];
}];
However, If what you want is just to flatten the json, you must use recursion and create a category similar to the following.
In NSJSONSerialization+FlattenedJSON.h
#interface NSJSONSerialization (FlattenedJSON)
+ (void)FlattenedJSONObjectWithData:(NSData *)data completionSuccessBlock:(void(^)(id aJson))onSuccess failure:(void(^)(NSError *anError))onFailure;
#end
In NSJSONSerialization+FlattenedJSON.m
#import "NSJSONSerialization+FlattenedJSON.h"
#implementation NSJSONSerialization (FlattenedJSON)
+ (void)FlattenedJSONObjectWithData:(NSData *)data completionSuccessBlock:(void (^)(id))onSuccess failure:(void (^)(NSError *))onFailure
{
NSError *error;
id object = [self JSONObjectWithData:data
options:kNilOptions
error:&error];
if (error)
{
onFailure(error);
}
else
{
NSMutableArray *result = [NSMutableArray array];
[self flatten:object
inArray:result];
onSuccess([result copy]);
}
}
+ (void)flatten:(id)anObject inArray:(NSMutableArray *)anArray
{
if ([anObject isKindOfClass:NSDictionary.class])
{
[((NSDictionary *)anObject) enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[self flatten:obj inArray:anArray];
}];
}
else if ([anObject isKindOfClass:NSArray.class])
{
[((NSArray *)anObject) enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self flatten:obj inArray:anArray];
}];
}
else
{
[anArray addObject:anObject];
}
}
#end
The question sounds weird but I'm getting an array of dictionaries as parsed result.
Something like this:
parsed content: (
{
"name" = "John";
"lastname" = "Doe";
"foo" = "bar";
}
What would be the suggestion for best way to create an array of values??
Like this?
- (void)flattenDictionary:(NSDictionary *)d intoKeys:(NSMutableArray *)keys andValues:(NSMutableArray *)values {
for (id key in [d allKeys]) {
[keys addObject:key];
[values addObject:[d valueForKey:key]];
}
}
- (void)flattenDictionaries:(NSArray *)arrayOfDictionaries {
NSMutableArray *keys = [NSMutableArray array];
NSMutableArray *values = [NSMutableArray array];
for (NSDictionary *d in arrayOfDictionaries) {
[self flattenDictionary intoKeys:keys andValues:values];
}
NSLog(#"now we have these values %#", values);
NSLog(#"corresponding to these keys %#", keys);
}
You can get the values with:
NSArray *values = dictionary.allValues;
Or, loop through it:
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
NSLog(#"%# = %#", key, object);
}];
To do that loop through them and create an array.
while removing the runtime memory leaks in my iPad application , I came across this strange memory leak in NSObject+JSONSerializableSupport class in the following method
+ (id) deserializeJSON:(id)jsonObject {
id result = nil;
if ([jsonObject isKindOfClass:[NSArray class]]) {
//JSON array
result = [NSMutableArray array];
for (id childObject in jsonObject) {
[result addObject:[self deserializeJSON:childObject]];
}
}
else if ([jsonObject isKindOfClass:[NSDictionary class]]) {
//JSON object
//this assumes we are dealing with JSON in the form rails provides:
// {className : { property1 : value, property2 : {class2Name : {property 3 : value }}}}
NSString *objectName = [[(NSDictionary *)jsonObject allKeys] objectAtIndex:0];
Class objectClass = NSClassFromString([objectName toClassName]);
if (objectClass != nil) {
//classname matches, instantiate a new instance of the class and set it as the current parent object
result = [[[objectClass alloc] init] autorelease];
}
NSDictionary *properties = (NSDictionary *)[[(NSDictionary *)jsonObject allValues] objectAtIndex:0];
NSDictionary *objectPropertyNames = [objectClass propertyNamesAndTypes];
for (NSString *property in [properties allKeys]) {
NSString *propertyCamalized = [[self convertProperty:property andClassName:objectName] camelize];
if ([[objectPropertyNames allKeys]containsObject:propertyCamalized]) {
Class propertyClass = [self propertyClass:[objectPropertyNames objectForKey:propertyCamalized]];
[result setValue:[self deserializeJSON:[propertyClass deserialize:[properties objectForKey:property]]] forKey:propertyCamalized];
}
}
}
else {
//JSON value
result = jsonObject;
}
return result;
}
I am getting the memory leak on this line
[result setValue:[self deserializeJSON:[propertyClass deserialize:[properties objectForKey:property]]] forKey:propertyCamalized];
Please suggest a solution or tell me where i am going wrong.
So I've got json-framework up and running on my project, but need help figuring out how to use it to parse this json string:
[
{
"id":"0",
"name":"name",
"info":"This is info",
"tags":
[
{
"id":"36",
"tag":"test tag"
},
{
"id":"37",
"tag":" tag 2"
}
],
"other":"nil"
},
{
"id":"1",
"name":"name",
"info":"This is info",
"tags":
[
{
"id":"36",
"tag":"test tag"
},
{
"id":"37",
"tag":" tag 2"
}
],
"other":"nil"
}
]
Any help and maybe sample code on how to go about this specific type of json would be great. Somehow I can't get it into a dictionary I can read out of. Thanks so much.
The reason why you can't get this string into a dictionary is because it isn't a dictionary, it's an array of dictionaries
You can get the values into an Objective-C object by storing it in an NSArray:
NSArray *objects = (NSArray*) [jsonString JSONValue];
Then, you can loop over those objects that are in the array:
for(NSDictionary *dict in objects) {
NSString *id = (NSString *) [dict objectForKey:#"id"];
NSString *name = (NSString *) [dict objectForKey:#"name"];
NSArray *tags = (NSArray *) [dict objectForKey: #"tags"];
//loop over tags here...
for(NSDictionary *tag in tags) {
NSString *tag_id = (NSString *) [tag objectForKey:#"id"];
NSString *tag_name = (NSString *) [tag objectForKey:#"tag"];
}
//...
}
I have some problem with JSON parsing. When I hit URL, I've got JSON response like this:
//JSON 1
{ "data":
{"array":
["3",
{"array":
[
{"id":"1","message":"Hello","sender":"inot"},
{"id":"2","message":"World","sender":"inot"},
{"id":"3","message":"Hi","sender":"marza"}
]
}
]
},
"message":"MSG0001:Success",
"status":"OK"
}
But if the result of data is just 1, the JSON response is like this:
//JSON 2
{ "data":
{"array":
["3",
{"array":
{"id":"3","message":"Hi","sender":"marza"}
}
]
},
"message":"MSG0001:Success",
"status":"OK"
}
I implement this code to get the id, message and sender value, and work fine on JSON 1, but error on JSON 2. I use JSON-Framework. And the question is how to detect that the JSON response is object ({ }) or array ([ ]) ??
// Parse the string into JSON
NSDictionary *json = [myString JSONValue];
// Get all object
NSArray *items = [json valueForKeyPath:#"data.array"];
NSArray *array1 = [[items objectAtIndex:1] objectForKey:#"array"];
NSEnumerator *enumerator = [array1 objectEnumerator];
NSDictionary* item;
while (item = (NSDictionary*)[enumerator nextObject]) {
NSLog(#"id = %#",[item objectForKey:#"id"]);
NSLog(#"message = %#",[item objectForKey:#"message"]);
NSLog(#"sender = %#",[item objectForKey:#"sender"]);
}
You can use id and check if the object that you get is NSArray or NSDictionary like this:
id item = [json valueForKeyPath:#"data.array"];
if ([item isKindOfClass:[NSArray class]]) {
// item is an array
}
else if ([item isKindOfClass:[NSDictionary class]]) {
// item is a dictionary
}