XML into JSON conversion in iOS - ios

I need to convert XML response to JSON and sand to the json To javaScript code.
My XML response:
<cell>
<Result>True</Result>
<sguid>02291c402-2220-422b-b199-f92f22e56d2f</sguid>
</cell>
I am using XMLReader supporting file from this site:
XMLReader
I am using this code to convert XML to JSON :
+ (NSString*) XMLToJson:(CXMLDocument *)xmlDocument
{
NSError *error = nil;
NSArray *resultNodes = [xmlDocument nodesForXPath:#"//cell" error:&error];
if(error)
NSLog(#"%#",error.description);
CXMLNode *cellNode = [resultNodes objectAtIndex:0];
NSLog(#"%#",cellNode.XMLString);
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLString:cellNode.XMLString error:&parseError];
NSLog(#"%#", xmlDictionary);
//{print this.
// cell = {
// Result = {
// text = True;
// };
// sguid = {
// text = "0391c402-1120-460b-b199-f92fffe56d2f";
// };
// };
//}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:xmlDictionary
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
if(error)
NSLog(#"%#",error.description);
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"%#", jsonString);
return jsonString;
}
I got JSON response like this:
{
"cell" : {
"Result" : {
"text" : "True"
},
"sguid" : {
"text" : "0391c402-1120-460b-b199-f92fffe56d2f"
}
}
}
I need JSON response like this:
{
"cell": {
"Result": "True",
"sguid": "02291c402-2220-422b-b199-f92f22e56d2f"
}
}
Because then I send this json to javascript code I get that exception jquery mobile dont know parser this and throws an exception of syntax error.
I've seen programmers use this solution and is helping them but I still get the same result in this solution.
XML into JSON conversion in iOS
thanks

I just wrote a function for your problem, I tried it on with a couple of XMLs. Let me know if you find any issues
- (NSMutableDictionary *)extractXML:(NSMutableDictionary *)XMLDictionary
{
for (NSString *key in [XMLDictionary allKeys]) {
// get the current object for this key
id object = [XMLDictionary objectForKey:key];
if ([object isKindOfClass:[NSDictionary class]]) {
if ([[object allKeys] count] == 1 &&
[[[object allKeys] objectAtIndex:0] isEqualToString:#"text"] &&
![[object objectForKey:#"text"] isKindOfClass:[NSDictionary class]]) {
// this means the object has the key "text" and has no node
// or array (for multiple values) attached to it.
[XMLDictionary setObject:[object objectForKey:#"text"] forKey:key];
}
else {
// go deeper
[self extractXML:object];
}
}
else if ([object isKindOfClass:[NSArray class]]) {
// this is an array of dictionaries, iterate
for (id inArrayObject in (NSArray *)object) {
if ([inArrayObject isKindOfClass:[NSDictionary class]]) {
// if this is a dictionary, go deeper
[self extractXML:inArrayObject];
}
}
}
}
return XMLDictionary;
}
And use it like this
NSDictionary *clearXML = [[self extractXML:[yourParsedXMLDictionary mutableCopy]] copy];

Your problem in using XMLReader. For resolve this problem you can use XMLConverter instead of the XMLReader.

Related

Converting NSString to JSON with NSJSONSerialization is not working

I have this function:
- (void)checkLogin:(NSString *)pLogin andPassword:(NSString*) pPassword {
//Create the data object.
NSMutableDictionary *tLoginAndPasword = [NSMutableDictionary dictionaryWithObjectsAndKeys:pLogin,#"Login",pPassword,#"Password", nil];
NSMutableDictionary *tData = [NSMutableDictionary dictionaryWithObjectsAndKeys:[_Util serializeDictionary:tLoginAndPasword],#"Data", nil];
//Call the login method.
NSData *tResponse = [_Util getLogin:tData];
if (tResponse != Nil) {
_oLabelErrorLogin.hidden = YES;
[_Util setUser:pLogin andPassword:pPassword];
NSMutableDictionary *tJSONResponse =[NSJSONSerialization JSONObjectWithData:tResponse options:kNilOptions error:nil];
NSString *tPayload = [tJSONResponse objectForKey:#"Payload"];
if([[tJSONResponse objectForKey:#"StatusCode"] isEqual: #"424"]) {
//Set global values.
NSData *tPayloadData = [tPayload dataUsingEncoding:NSUTF8StringEncoding];
if ([NSJSONSerialization isValidJSONObject:tPayloadData]) {
_Payload = [NSJSONSerialization JSONObjectWithData:tPayloadData options:kNilOptions error:nil];
_RowCount = _Payload.count;
} else {
NSLog(#"JSON Wrong String %#",tPayload);
}
} else if([[tJSONResponse objectForKey:#"StatusCode"] isEqual: #"200"]){
_Payload = Nil;
}
} else {
//Set global values.
_Payload = Nil;
_oLabelErrorLogin.hidden = NO;
//Clear login data.
_oLogin.text = #"";
_oPassword.text = #"";
[_Util setUser:#"" andPassword:#""];
}
}
The JSON response looks like this:
{
"Payload": "{\"UserName\":\"Marco Uzcátegui\",\"Clients\":[{\"UserProfileId\":4,\"ProfileName\":\"Platform Administrator\",\"ClientName\":\"Smart Hotel Platform\",\"InSession\":true},{\"UserProfileId\":5,\"ProfileName\":\"Administrator\",\"ClientName\":\"La Moncloa de San Lázaro\",\"InSession\":false},{\"UserProfileId\":6,\"ProfileName\":\"Administrator\",\"ClientName\":\"Jardín Tecina\",\"InSession\":false}]}",
"StatusCode": "424",
"StatusDescription": null
}
As you can see, I have a escaped string inside "Payload" that is a correct JSON, so I want to generate another NSMutableDictionary with that string, so I'm doing this:
NSData *tPayloadData = [tPayload dataUsingEncoding:NSUTF8StringEncoding];
if ([NSJSONSerialization isValidJSONObject:tPayloadData]) {
_Payload = [NSJSONSerialization JSONObjectWithData:tPayloadData options:kNilOptions error:nil];
_RowCount = _Payload.count;
} else {
NSLog(#"JSON Wrong String %#",tPayload);
}
So I'm creating an NSData from the NSString and asking if is valid, it always returns false.
I have tried to replace the "\" from the string and is not working.
[tPayload stringByReplacingOccurrencesOfString:#"\\\"" withString:#""]
I have tried to create a NSMutableDictionary with the string, but the result is not a dictionary.
NSMutableDictionary *tPayload = [tJSONResponse objectForKey:#"Payload"];
I'm kind of lost here.
Any help will be appreciated.
Regards.
The issue is this line
[NSJSONSerialization isValidJSONObject:tPayloadData]
From the documentation of isValidJSONObject
Returns a Boolean value that indicates whether a given object can be
converted to JSON data.
given object means an NSArray or NSDictionary but not NSData
Remove that check and implement the error parameter in JSONObjectWithDataoptions:error:
The method NSJSONSerialization.isValidJSONObject: checks if an object (e.g. a NSDictonary or NSArray instance) can be converted to JSON. It doesn't check if a NSData instance can be converted from JSON. For NSData, it will always return false.
So just call NSJSONSerialization.JSONObjectWithData:options: and check the result instead.

Assigning a dictionary to a variable

When check self.weatherData, I get nothing even though there is data in "data". Here is my function:
- (void)handleNetworkResponse:(NSData *)myData
{
//NSMutableDictionary *data = [NSMutableDictionary dictionary];
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
// now we'll parse our data using NSJSONSerialization
id myJSON = [NSJSONSerialization JSONObjectWithData:myData options:NSJSONReadingMutableContainers error:nil];
// typecast an array and list its contents
NSDictionary *jsonArray = (NSDictionary *)myJSON;
// take a look at all elements in the array
for (id element in jsonArray) {
id key = [element description];
id innerArr = [jsonArray objectForKey:key];
NSDictionary *inner = (NSDictionary *)innerArr;
if ([inner conformsToProtocol:#protocol(NSFastEnumeration)]) {
for(id ele in inner) {
id innerKey = [ele description];
[data setObject:[[inner valueForKey:innerKey] description] forKey:[ele description]];
}
}
else {
[data setObject:[inner description] forKey:[element description]];
}
}
NSLog([data description]);
self.weatherData = data;
}
However when check self.weatherData, I get nothing even though there is data in "data".
Issue was data isn't there when I assign it to the variable from the an asynchronous method :D
all fixed now by adding a delegate call back

Parsing JSON information in Objective C (multiple levels)

I'm able to parse a part of my JSON file but if I want to go deeper in the structure, I'm lost. Here's my JSON :
{
"album":[
{
"album_titre":"Publicité",
"album_photo":"blabla.jpg",
"album_videos":[
{
"titre_video":"Chauffage Compris",
"duree_video":"01'25''",
"photo_video":"chauffage.jpg",
"lien_video":"www.bkjas.jhas.kajs"
},
{
"titre_video":"NIFFF 2012",
"duree_video":"01'43''",
"photo_video":"nifff.jpg",
"lien_video":"www.bkjas.jhas.kajs"
}
]
},
{
"album_titre":"Events",
"album_photo":"bloublou.jpg",
"album_videos":[
{
"titre_video":"Auvernier Jazz",
"duree_video":"01'15''",
"photo_video":"auvernier.jpg",
"lien_video":"www.bkjas.jhas.kajs"
},
{
"titre_video":"NIFFF 2011",
"duree_video":"01'03''",
"photo_video":"nifff2011.jpg",
"lien_video":"www.bkjas.jhas.kajs"
}
]
},
{
"album_titre":"Culture",
"album_photo":"bilibl.jpg"
},
{
"album_titre":"Postproduction",
"album_photo":"bizoubzou"
}
]
}
And here's my objective-c code :
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary *document = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
if (document==nil)
{
NSLog( #"oops\n%#", error);
}
NSArray *album = document[#"album"];
for( NSDictionary *albumDictionary in album )
{
[album_titre addObject:albumDictionary[#"album_titre"]];
[album_photo addObject:albumDictionary[#"album_photo"]];
for( NSDictionary *album_videosDictionary in albumDictionary[#"album_videos"])
{
[titre_video addObject:album_videosDictionary[#"titre_video"]];
[duree_video addObject:album_videosDictionary[#"duree_video"]];
[photo_video addObject:album_videosDictionary[#"photo_video"]];
[lien_video addObject:album_videosDictionary[#"lien_video"]];
}
}
[self.tableView reloadData];
}
What I can't achieve is to create an array with for example contains all "titre_video" corresponding to "album_titre":"publicité". So it should contain "Chauffage Compris" and "Nifff 2012".
I know it's a kind of easy question but I've search for a while and still not able to do it.
Thank's a lot.
Nicolas
The key is to understand JSON structure:
{ } - - this means the underlying object is a dictionary.
[ ] -- this means the underlyingobject is an array
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary *document = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
// all titre:video for album_titre:publicite
NSArray *albumArray = [document objectForKey:#"album"];
NSDictionary *dict = [albumArray objectAtindex:0];
NSArray *videos = [dict objectForKey:#"album_videos"];
// to fetch Videos inside album_videos
// here you will get al the videos inside key titre_video
NSMutableArray *titreVideoArray = [[NSMutableArray alloc]init];
for(int i=0; i< videos.count; i++){
NSDictionary *dict = [videos objectAtindex:i];
NSArray *titreVideos = [dict objectForKey:#"titre_video"];
[titreVideoArray addObject: titreVideos];
}
}
It seems you want to fetch all the videos relating to different "album_titre".
I would suggest you to use NSPredicate .
NSArray *videos = [self videosArrayForTitle:#"Publicité" albumArray:albumArray];
Here we pass title and the albumArray from above to fetch us the videos array.
- (NSArray *)videosArrayForTitle:(NSString *)title albumArray:(NSArray *)albumArray{
NSPredicate *resultPredicate=[NSPredicate predicateWithFormat:#"SUBQUERY(album_titre, $content, $content CONTAINS %#).#count > 0", title];
NSArray *searchResults=[albumArray filteredArrayUsingPredicate:resultPredicate];
NSArray *videos = [searchResults objectForKey:#"album_videos"];
return videos;
}
{ } denotes NSDictionary
[ ] denotes NSArray
Copy your json into a text edit file and go in deep. You can use NSLog() to print the data, when you go deep.
Hope it will help you.

How should I read the data from a json string? iphone

I have in a NSString "[{"van" : 1,312, "vuan":12,123}] and in order to get this values for every key, I am doing this:
NSData *data1 = [jsonResponse1 dataUsingEncoding:NSUTF8StringEncoding];
jsonArray = [NSJSONSerialization JSONObjectWithData:data1 options:kNilOptions error:&err];
self.van = [NSMutableArray arrayWithCapacity:1];
self.vuan = [NSMutableArray arrayWithCapacity:1];
for (NSDictionary *json in jsonArray) {
NSString * value = [json objectForKey:#"van"];
[self.van addObject:value];
lbl1.text = value;
NSString * value1 = [json objectForKey:#"vuan"];
[self.vuan addObject:value1];
lbl4.text = value1;
}
May be I don't have to use an array and instead to convert the NSData directly in a NSDictionary.
Anyway, I don't understand why jsonArray is nil, although jsonResponse1 contains the values I have written above.
EDIT: My boss have written the json string wrong. Thank you all for your suggestions!:)
Your JSON is invalid. Fix it. This site is your friend.
http://jsonlint.com/
You need to code more defensively and you need to report errors as they are found.
Firstly check if the JSON parsing failed and if so report the error:
NSData *data1 = [jsonResponse1 dataUsingEncoding:NSUTF8StringEncoding];
jsonArray = [NSJSONSerialization JSONObjectWithData:data1 options:kNilOptions error:&err];
if (jsonArray == nil)
{
NSLog(#"Failed to parse JSON: %#", [err localizedDescription]);
return;
}
Secondly if those keys are not in the JSON, objectForKey: will return nil and when you attempt to add that to the arrays, it will throw an exception, which is something you want to avoid:
for (NSDictionary *json in jsonArray) {
NSString * value = [json objectForKey:#"van"];
if (value != nil)
{
[self.van addObject:value];
lbl1.text = value;
}
else
{
NSLog(#"No 'van' key in JSON");
}
NSString * value1 = [json objectForKey:#"vuan"];
if (value1 != nil)
{
[self.vuan addObject:value1];
lbl4.text = value1;
}
else
{
NSLog(#"No 'vuan' key in JSON");
}
}
So in summary: runtime errors will occur so you need to ensure you handle them. When they occur you need to report them with as much information possible so that you can diagnose and fix them.

NSNull value inside a object generated by JSONKit (or similar)

I'm storing the result of JSONKit parse in a key/value database (LevelDB), but the JSON I'm downloading has some filed set to null, and this won't let you serialize the corresponding generated object (NSArray or NSDictionary), to store it as an object.
¿Any idea how can I deep iterate over a NSSomething (Dictionary or Array) to change those values?
There is a post https://github.com/johnezang/JSONKit/issues/25 that explains how to modify the framework to omit it from dictionaries and array's
Sometime it happened to me that a null value was set to something what was not recognized neither as NSNull nor as NSString. Therefore i´ve replaced all null strings in the json string before i parse it with NSJSONSerialization. I´ve read the data into a NSData object, copied it into a NSString object, replaced the null strings and copied it again into a NSData object as NSJSONSerialization expects a NSData object. Maybe you can write it shorter but it works.
Here´s the code
NSString *jsonPath = [myPath stringByAppendingPathComponent:#"myDataFile.json"];
NSMutableData *myJSON = [[NSMutableData alloc] initWithContentsOfFile:jsonPath];
NSString *jsonString = [[NSString alloc] initWithBytes:myJSON.bytes length:myJSON.length encoding:NSUTF8StringEncoding];
jsonString = [jsonString stringByReplacingOccurrencesOfString:#"null" withString:#"\"placeholder\""];
NSData * jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&jsonParsingError];
after that all previous null occurances will contain a placeholder string.
I parsed the JSON to a mutableObject [[JSONDecoder decoder] mutableObjectWithUTF8String:(const unsigned char *) [json UTF8String] length:[json lengthOfBytesUsingEncoding:NSUTF8StringEncoding] error:nil ]; and then used this code to fix it:
-(id) fixObject: (id) a
{
if([a isKindOfClass:[NSMutableDictionary class]])
{
NSMutableDictionary *ad = a;
for (NSObject *key in ad)
{
if([[ad objectForKey:key] isKindOfClass:[NSMutableDictionary class]] || [[ad objectForKey:key] isKindOfClass:[NSMutableArray class]])
[self fixObject:[ad objectForKey:key]];
else
{
if((NSNull *)[ad objectForKey:key] == [NSNull null]) [ad setObject:#"" forKey:key];
}
}
}else if([a isKindOfClass:[NSMutableArray class]])
{
NSMutableArray *ar = a;
for (NSObject *ob in ar)
{
if([ob isKindOfClass:[NSMutableDictionary class]] || [ob isKindOfClass:[NSMutableArray class]])
{
[self fixObject:ob];
}
else if((NSNull *)ob == [NSNull null])
{
[ar removeObject:ob];
}
}
}
return a;
}
If you find a better way to do this, let me know!

Resources