Parsing Poorly formed JSON in objective-C - objective-c

My task is to parse some JSON which was created by running an XML to JSON conversion tool on an XML WADL. I'm able to parse the data returned in the response into JSON and I'm able to obtain the top level NSDictionary from the data. I can get an array from the dictionary and an NSDictionary from the Array ( it includes the key value but thats it) and thats as deep as I can go. I've done parsing in the past but this particular JSON format I am having no luck? Here is the code I'm using..
// Decode the data
NSError *parseError = nil;
NSData *jsonData = [request responseData];
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&parseError];
if (parseError) {
NSLog(#"Error: %#", [parseError localizedDescription]);
// other stuff..
return;
}
NSLog(#"JSON=: %#", responseDict.description);
NSArray *messageBoxResponse = [responseDict objectForKey:#"messageBoxResponse"];
NSLog(#"messageBoxResponse=: %#", messageBoxResponse);
NSUInteger count = messageBoxResponse.count;
for (NSDictionary* messages in messageBoxResponse) {
NSLog(#"Messages=: %#", messages.description);
NSArray *message = [messages objectForKey:#"message"];
// get SIGABRT
count = message.count;
// If I comment out above line and introduce this I get SIGABRT also
for (NSDictionary* something in message) {
NSLog(#"Somthing=: %#", something.description);
}
Here is the JSON I'm attempting to parse.. IPs have been changed :):
{
messageBoxResponse = {
messages = {
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages";
rel = self;
};
message = (
{
flags = {
answered = 0;
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<4F3131A3.6040204#sc-msg1-msg.sc.sc>/flags";
rel = self;
};
taggedForDeletion = 0;
unread = 0;
};
from = "Suren.1#sc-msg1-msg.sc.sc";
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<4F3131A3.6040204#sc-msg1-msg.sc.sc>";
rel = self;
};
parts = {
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<4F3131A3.6040204#sc-msg1-msg.sc.sc>/parts";
rel = self;
};
part = {
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<4F3131A3.6040204#sc-msg1-msg.sc.sc>/parts/0";
rel = self;
};
mimeType = "TEXT/PLAIN";
name = "text.txt";
size = 564;
};
};
receivedDate = 1328624061000;
sentDate = 1328624035000;
subject = test;
},
{
flags = {
answered = 0;
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<24346739.35.1328562602976.JavaMail.mango#sc-msg1-msg.sc.sc>/flags";
rel = self;
};
taggedForDeletion = 0;
unread = 0;
};
from = "Suren.1#sc-msg1-msg.sc.sc";
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<24346739.35.1328562602976.JavaMail.mango#sc-msg1-msg.sc.sc>";
rel = self;
};
parts = {
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<24346739.35.1328562602976.JavaMail.mango#sc-msg1-msg.sc.sc>/parts";
rel = self;
};
part = (
{
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<24346739.35.1328562602976.JavaMail.mango#sc-msg1-msg.sc.sc>/parts/0";
rel = self;
};
mimeType = "TEXT/PLAIN";
name = "text.txt";
size = 6;
},
{
content = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<24346739.35.1328562602976.JavaMail.mango#sc-msg1-msg.sc.sc>/parts/1/2c3a3400620f218d5378607260dc2749.wav";
rel = content;
};
duration = 3;
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<24346739.35.1328562602976.JavaMail.mango#sc-msg1-msg.sc.sc>/parts/1";
rel = self;
};
mimeType = "AUDIO/WAV";
name = "Audio_Recording_S000551_002.wav";
size = 31190;
},
{
link = {
href = "http://1.1.1.1:80/services/messageboxes/63358/messages/<24346739.35.1328562602976.JavaMail.mango#sc-msg1-msg.sc.sc>/parts/2";
rel = self;
};
mimeType = "APPLICATION/MS-TNEF";
name = "winmail.dat";
size = 656;
}
);
};
receivedDate = 1328562604000;
sentDate = 1328562596000;
subject = "Voice Message from Suren 1 (63357)";
}
);
};
};
}

Its because the json is not valid. It should look more like this:
{
"messages": {
"link": {
"href": "http: //1.1.1.1: 80/services/messageboxes/63358/messages",
"rel": "self"
}
}
}
the '=' need to be ':' there are semicolons that shouldn't be there.

Related

GTMAppAuth + MailCore: "A stable connection to the server could not be established."

under iOS using GMTAuth to access gmail. The test code follows below. The account is accessible with MailCore, essentially similar code, but user/pw no oAuth. Any clues would be appreciated.
I get this log output:
__nw_connection_get_connected_socket_block_invoke 3 Connection has no connected handler
2017-02-24 17:20:02.977 Example-iOS[38329:24679819] finished checking account.
2017-02-24 17:20:10.526 Example-iOS[38329:24679819] error loading account: Error Domain=MCOErrorDomain Code=1 "A stable connection to the server could not be established."
and this is the code:
self.imapSession = [[MCOIMAPSession alloc] init];
self.imapSession.hostname = #"imap.google.com";
self.imapSession.port = 993;
self.imapSession.username = [_authorization userEmail];
GTMAppAuthFetcherAuthorization* authorization =
[GTMAppAuthFetcherAuthorization authorizationFromKeychainForName:kExampleAuthorizerKey];
self.imapSession.OAuth2Token = authorization.authState.lastTokenResponse.accessToken;
self.imapSession.authType = MCOAuthTypeXOAuth2;
self.imapSession.connectionType = MCOConnectionTypeTLS;
GTMAppAuthExampleViewController * __weak weakSelf = self;
self.imapSession.connectionLogger = ^(void * connectionID, MCOConnectionLogType type, NSData * data) {
#synchronized(weakSelf) {
if (type != MCOConnectionLogTypeSentPrivate) {
NSLog(#"event logged:%p %li withData: %#", connectionID, (long)type, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
}
};
// Reset the inbox
self.messages = nil;
NSLog(#"checking account");
self.imapCheckOp = [self.imapSession checkAccountOperation];
[self.imapCheckOp start:^(NSError *error) {
GTMAppAuthExampleViewController *strongSelf = weakSelf;
NSLog(#"finished checking account.");
if (error == nil) {
// TBD: [strongSelf loadLastNMessages:NUMBER_OF_MESSAGES_TO_LOAD];
} else {
NSLog(#"error loading account: %#", error);
}
strongSelf.imapCheckOp = nil;
}];
}
Update: I figured out the solution. Here's my full working code:
func loadAccount() {
// This is just a model file holding the account details...
let account = emailAccounts[currentAccount]
imapSession = MCOIMAPSession()
imapSession?.hostname = account.hostname
imapSession?.port = 993
imapSession?.username = account.userName
imapSession?.authType = .xoAuth2
// This email helper code is from this guide:
// https://github.com/MailCore/mailcore2/wiki/Implementing-OAuth-2.0
imapSession?.oAuth2Token = EmailHelper.singleton().authorization?.authState.lastTokenResponse?.accessToken
// This is important too (wasn't working with other values)
imapSession?.connectionType = .TLS
imapSession?.connectionLogger = { [unowned self] (connectionID, type, data) in
let lockQueue = DispatchQueue(label: "com.inboxzero.LockQueue")
lockQueue.sync() {
if (type != MCOConnectionLogType(rawValue: NSInteger(2))) { // MCOConnectionLogTypeSentPrivate
if let theData = data, let str = connectionID {
let theString = String(describing: theData)
print("event logged:\(str) \(type) withData: \(theString)")
}
}
}
}
// Reset the inbox:
messages = nil
isLoading = false
print("checking account \(self.imapSession!.username!)")
imapCheckOp = self.imapSession?.checkAccountOperation()
if let checkOp = imapCheckOp {
checkOp.start( { (error) in
print("finished checking \(self.imapSession!.username!)")
if (error == nil) {
self.loadLastNMessages(nMessages: self.NUMBER_OF_MESSAGES_TO_LOAD)
}
else {
print("error loading account \(self.imapSession!.username!): %#", error!)
self.alertWithTitle(title:"Mail Core", message:error.debugDescription)
return
}
})
}
}

XML to JSON convert issue. I want to change it in array of dictionary structure. is it possible?

I want to change it in array of dictionary structure. is it possible? Actually I have a XML structure, while converting xml to json, incase it is having one value, it gives dictionary structure, otherwise array structure, can you please apprise how to handle/parse it.
INCASE OF ONE VALUE
item = {
"ML_KEY" = {
text = "test1";
};
name = {
text = "test2";
};
order = {
text = 1;
};
value = {
text = "Test3"
};
};
INCASE OF MORE THAN ONE VALUES
item = (
{
"ML_KEY" = {
text = "Testing4";
};
name = {
text = "Testing3";
};
order = {
text = 1;
};
value = {
text = "TestingB";
};
},
{
"ML_KEY" = {
text = "New2";
};
name = {
text = "New";
};
order = {
text = 2;
};
value = {
text = "Preview"
};
},
{
"ML_KEY" = {
text = "Testing2"
};
name = {
text = Remove;
};
order = {
text = 3;
};
value = {
text = Remove;
};
},
{
"ML_KEY" = {
text = "Testing";
};
name = {
text = "E";
};
order = {
text = 4;
};
value = {
text = "D";
};
}
);
};
You should check for the class type of the data you are getting. You can do it like this.
id items =[[NSDictionary dictionaryWithXMLString:string] valueForKey:#"items"];
if ([items isKindOfClass:[NSDictionary class]])
{
// parse your dictionary here
}else if([items isKindOfClass:[NSArray class]])
{
// parse your array here
}else{
}
NSDictionary *responseDict = XMLResponse;
for (NSDictionay * dict in responseDict){
__do stuff here__
}
you can also work with NSMutableDictionay, that way you can add multiple lines as you go throw the response
Yes I did the same as above with slight changes:
id checkDict = [tempDict valueForKeyPath:#"items.item"];
if ([checkDict isKindOfClass:[NSDictionary class]])
{
// parse your dictionary here
}else if([checkDict isKindOfClass:[NSArray class]])
{
// parse your array here
}else{
}

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]

My XML response:
{
"S:Envelope" = {
"S:Body" = {
"ns2:getMatchListResponse" = {
item = (
{
answerTime = {
text = 30;
};
challengerAppealsGranted = {
text = "0 of 16";
};
challengerHandle = {
text = manish;
};
challengerMatchesPlayed = {
text = 93;
};
challengerPic = {
text = "image.png";
};
challengerScore = {
text = 0;
};
challengerlosses = {
text = 0;
};
challengerwins = {
text = 4;
};
handle1 = {
text = sahni;
};
handle1AppealsGranted = {
text = 5;
};
handle1MatchesPlayed = {
text = 84;
};
handle1Response = {
text = Pending;
};
handle1Score = {
text = 0;
};
handle1losses = {
text = 0;
};
handle1wins = {
text = 1;
};
handle2MatchesPlayed = {
text = 0;
};
handle2Score = {
text = 0;
};
handle2losses = {
text = 0;
};
handle2wins = {
text = 0;
};
handle3MatchesPlayed = {
text = 0;
};
handle3Score = {
text = 0;
};
handle3losses = {
text = 0;
};
handle3wins = {
text = 0;
};
idMatch = {
text = 750;
};
isAppeal = {
text = false;
};
isFreeForm = {
text = false;
};
isMultichoiceQuestion = {
text = false;
};
isPublic = {
text = false;
};
matchName = {
text = ewtwert;
};
matchStartThresholdTime = {
text = "4 days 7 hrs";
};
matchStatus = {
text = wait;
};
matchType = {
text = Private;
};
noOfPlayers = {
text = 2;
};
priorityInList = {
text = 0;
};
scoreToWin = {
text = 5;
};
timeDuration = {
text = "5 days";
};
turnChangesIn = {
text = 0;
};
},
{
answerTime = {
text = 30;
};
challengerAppealsGranted = {
text = "0 of 16";
};
challengerHandle = {
text = manish;
};
challengerMatchesPlayed = {
text = 93;
};
challengerPic = {
text = "image.png";
};
challengerScore = {
text = 0;
};
challengerlosses = {
text = 0;
};
challengerwins = {
text = 4;
};
handle1MatchesPlayed = {
text = 0;
};
handle1Score = {
text = 0;
};
handle1losses = {
text = 0;
};
handle1wins = {
text = 0;
};
handle2MatchesPlayed = {
text = 0;
};
handle2Score = {
text = 0;
};
handle2losses = {
text = 0;
};
handle2wins = {
text = 0;
};
handle3MatchesPlayed = {
text = 0;
};
handle3Score = {
text = 0;
};
handle3losses = {
text = 0;
};
handle3wins = {
text = 0;
};
idMatch = {
text = 749;
};
isAppeal = {
text = false;
};
isFreeForm = {
text = false;
};
isMultichoiceQuestion = {
text = false;
};
isPublic = {
text = false;
};
matchName = {
text = gfhf;
};
matchStartThresholdTime = {
text = "4 days 6 hrs";
};
matchStatus = {
text = wait;
};
matchType = {
text = Public;
};
noOfPlayers = {
text = 2;
};
priorityInList = {
text = 0;
};
scoreToWin = {
text = 5;
};
timeDuration = {
text = "5 days";
};
turnChangesIn = {
text = 0;
};
}
);
"xmlns:ns2" = "http://services.tgs.com/";
};
};
"xmlns:S" = "http://schemas.xmlsoap.org/soap/envelope/";
};
}
I need value of key "matchStartThresholdTime".
I do:
NSDictionary *dictResult = [XMLReader dictionaryForXMLString:responseString error:nil];
NSDictionary *Enveloper = [dictResult objectForKey:#"S:Envelope"];
NSDictionary *Body = [Enveloper objectForKey:#"S:Body"];
NSDictionary *profileDetails = [Body objectForKey:#"ns2:getMatchListResponse"];
NSMutableArray *items = [profileDetails objectForKey:#"item"];
// NSLog(#"items===>%#",items);
NSDictionary *temp1;
for(temp1 in items)
{
thresholdTime = [NSString stringWithFormat:#"%#",[[temp1 objectForKey:#"matchStartThresholdTime"]objectForKey:#"text"]];...thresholdTime is NSString object.......and this line causes exception
//NSLog(#"time is===>%#",[[temp1 objectForKey:#"matchStartThresholdTime"]objectForKey:#"text"]);
}
What is the problem here?
Temp1 contains an NSString Object and not the NSDictionary, that you expect.
When dealing with JSON it is wise always to (double) check if a received object is really of the type that you expect. Always use
if ([temp1 isKindOfClass:[NSDictionary class]]) ...
or so.

how to get pi_image from array in table view

(
{
property = {
"p_address" = sdfsdf;
"p_asking_price" = "50000.00";
"p_category_type" = 1;
"p_created" = "0000-00-00 00:00:00";
"p_description" = sdfsdf;
"p_id" = 2;
"p_is_new_property" = 1;
"p_modified" = "2013-04-08 15:40:25";
"p_no_of_bedroom" = 1;
"p_no_of_otherroom" = 1;
"p_no_of_wc" = 2;
"p_title" = sadf;
"p_type" = demo;
};
"property_images" = (
);
"property_local_information" = (
{
"li_label" = "Nearby Transport";
"li_order" = 1;
"pli_distance" = "";
"pli_logo" = "";
"pli_title" = "";
}
);
"property_sale_history" = (
{
"psh_history" = sdsdfsd;
},
{
"psh_history" = sdfdfds;
}
);
"property_videos" = (
);
},
{
property = {
"p_address" = dfgsdfg;
"p_asking_price" = "44222.00";
"p_category_type" = "";
"p_created" = "0000-00-00 00:00:00";
"p_description" = "Updated by a staff meber (demo2#gmail.com)";
"p_id" = 3;
"p_is_new_property" = 1;
"p_modified" = "2013-04-09 03:05:09";
"p_no_of_bedroom" = 0;
"p_no_of_otherroom" = 0;
"p_no_of_wc" = 0;
"p_title" = "Test Update";
"p_type" = sdfgsdfgsdg;
};
"property_images" = (
{
"pi_image" = "prop_img_1594785781_3.png";
}
);
"property_local_information" = (
{
"li_label" = "Nearby College";
"li_order" = 4;
"pli_distance" = utyutyu;
"pli_logo" = "";
"pli_title" = tyutyu;
}
);
"property_sale_history" = (
{
"psh_history" = testing;
},
{
"psh_history" = tyutyutut;
}
);
"property_videos" = (
{
"pv_video" = "prop_vid_730342365_3.flv";
}
);
},
Try this if your using json concept
NSString *urlString = [NSString stringWithFormat:"your url link"];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
NSMutableArray *json = (NSMutableArray*)[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSMutableArray *piimage=[json valueForKey:#"pi_image"];
NSLog(#"%#",piimage);

extracting information from NSDictionary

I have a NSDictionary response from a Flickr api request and it's description looks like this:
self.userInfo: {
"_text" = "\n\n";
person = {
"_text" = "\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n";
description = {
};
iconfarm = 0;
iconserver = 0;
id = "83943196#N02";
ispro = 0;
location = {
};
"mbox_sha1sum" = {
"_text" = 7b61c5d24f12345678be82c31234567830540;
};
mobileurl = {
"_text" = "http://m.flickr.com/photostream.gne?id=12345678";
};
nsid = "12345678#N02";
"path_alias" = "";
photos = {
"_text" = "\n\t\t\n\t\t\n\t\t\n\t\t\n\t";
count = {
"_text" = 2;
};
firstdate = {
"_text" = 12345678;
};
firstdatetaken = {
"_text" = "2012-08-01 12:46:38";
};
views = {
"_text" = 0;
};
};
photosurl = {
"_text" = "http://www.flickr.com/photos/12345678#N02/";
};
profileurl = {
"_text" = "http://www.flickr.com/people/12345678#N02/";
};
realname = {
"_text" = "Me TheUser";
};
timezone = {
label = "Pacific Time (US & Canada); Tijuana";
offset = "-08:00";
};
username = {
"_text" = metheuser;
};
};
stat = ok;
}
I'm having truoble figuring out how to extract the realname value into a NSString.
I've tried:
NSString * temp = [self.userInfo valueForKey:#"realname"];
NSLog (#"FL: nameOfSignedInUser. nameself.userInfo: %#", temp.debugDescription);
but that comes back as nil.
thank you!
NSString *name = [self.userInfo valueForKeyPath:#"person.realname._text"];
NSString *realName = [[[self.userInfo objectForKey:#"person"] objectForKey:#"realname"] objectForKey:#"_text"];