Parsing a JSON array with dictionaries - ios

I'm having some trouble getting to the data I want to in the JSON file. Here is a shortened version of the output from my console:
{
AUD = {
15m = "125.15547";
24h = "124.74";
buy = "121.0177";
last = "125.15547";
sell = "123.44883";
symbol = "$";
};
BRL = {
15m = "120.34";
24h = "120.34";
buy = "120.34";
last = "120.34";
sell = "120.34";
symbol = "R$";
};
CAD = {
15m = "129.08612";
24h = "131.07";
buy = "128.66227";
last = "129.08612";
sell = "129.08612";
symbol = "$";
};
}
I'm trying to parse the file using the built in JSON parsing library. Here is the parser in my viewDidLoad method:
_tickerArray = [NSMutableArray array];
NSURL *tickerDataURL = [NSURL URLWithString:#"https://blockchain.info/ticker"];
NSData *jsonData = [NSData dataWithContentsOfURL:tickerDataURL];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"%#", dataDictionary);
NSArray *ar = [NSArray arrayWithObject:dataDictionary];
for (NSString *key in [dataDictionary allKeys]) {
for (NSDictionary *dict in ar) {
TickerData *t;
t.currency = [dict objectForKey:key];
t.symbol = [dict objectForKey:#"symbol"];
t.last = [dict objectForKey:#"last"];
[_tickerArray addObject:t];
}
}
I want to store the currency code (like AUD or BRL) into t.currency along with some of the other data contained in the currency dictionary but now my app is crashing.
Error code:
NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil
None of the objects seem to get added to the _tickerArray
Help?
EDIT: Getting the keys to display with the proper data populating other fields:
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"%#", dataDictionary);
for (NSString *key in [dataDictionary allKeys]) {
NSDictionary *dic=[dataDictionary objectForKey:key];
TickerData *t=[[TickerData alloc] init];
t.currency = key;//EDITED
t.symbol = [dic objectForKey:#"symbol"];
t.last = [dic objectForKey:#"last"];
[_tickerArray addObject:t];
}

t is nil, you have to alloc/ init it:
TickerData *t = [[TickerData alloc] init];

NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"%#", dataDictionary);
//NSArray *ar = [NSArray arrayWithObject:dataDictionary];//REMOVED
for (NSString *key in [dataDictionary allKeys]) {
NSDictionary *dic=[dataDictionary objectForKey:key];//ADDED
for (NSString *dickey in [dic allKeys]) { //MODIFIED
NSDictionary *dict=[dic objectForKey:dicKey];//ADDED
TickerData *t=[[TickerData alloc] init];//ALLOC INIT ?
t.currency = key;//EDITED
t.symbol = [dict objectForKey:#"symbol"];
t.last = [dict objectForKey:#"last"];
[_tickerArray addObject:t];
}
}
Your data doesn't contain any array, its all dictionaries, try the above code see comments too..
Hope it works..
Edited:
Yes you have initialize the object too, as suggested above in other answers..

Try it....
NSURL *url = [NSURL URLWithString:#"https://blockchain.info/ticker"];
NSLog(#"API : %#",url);
NSMutableData *jsonData = [NSMutableData dataWithContentsOfURL:url];
NSString *data = [[NSString alloc] initWithBytes: [jsonData mutableBytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
dictionary = [data JSONValue];
NSDictionary *dict = [dictionary objectForKey:#"AUD"];
NSLog(#"%#",dict);
NSString *last = [dict valueForKey:#"last"];
NSLog(#"%#",last);

Related

How to parse such a json array?

Im having hard time while trying to parse the following json array. How to parse it. The other answers in web doesn't seem to solve my problem.
{
"status": 1,
"value": {
"details": [
{
"shipment_ref_no": "32",
"point_of_contact": {
"empid": ""
},
"products": {
"0": " Pizza"
},"status": "2"
},
{
"shipment_ref_no": "VAPL/EXP/46/14-15",
"point_of_contact": {
"empid": "60162000009888"
},
"products": {
"0": "MAIZE/CORN STARCH"
},
"status": "5"
}
]
}
}
I have to access the values of each of those keys.
Following is my code
NSString* pendingResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *jsonData = [pendingResponse dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
NSArray *argsArray = [[NSArray alloc] initWithArray:[jsonDic objectForKey:#"details"]];
NSDictionary *argsDict = [[NSDictionary alloc] initWithDictionary:[argsArray objectAtIndex:0]];
NSLog(#"keys = %#", jsonDic[#"values"]);
This is how you can parse your whole dictionary:
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray *details = [[dataDictionary objectForKey:#"value"] objectForKey:#"details"];
for (NSDictionary *dic in details) {
NSString *shipmentRefNo = dic[#"shipment_ref_no"];
NSDictionary *pointOfContact = dic[#"point_of_contact"];
NSString *empId = pointOfContact[#"empid"];
NSDictionary *products = dic[#"products"];
NSString *zero = products[#"0"];
NSString *status = dic[#"status"];
}
NSString *pendingResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *jsonData = [pendingResponse dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
NSArray *argsArray = [[NSArray alloc] initWithArray:[jsonDic objectForKey:#"details"]];
//argsArray holds objects in form of NSDictionary.
for(NSDictionary *response in argsArray) {
//String object
NSLog(#"%#", [response valueForKey:#"shipment_ref_no"]);
//Dictionary object
NSLog(#"%#", [[response objectForKey:#"point_of_contact"] valueForKey:#"empid"]);
//String object
NSLog(#"%#", [response valueForKey:#"status"]);
//Dictionary object
NSLog(#"%#", [[response objectForKey:#"products"] valueForKey:#"0"]);
}
I believe you should surely ask your server developer to update the response format.
Also, you can always use Model classes to parse your data. Please check this, How to convert NSDictionary to custom object.
And yes, I'm using this site to check my json response.
EDIT: Following answer is in javascript!
You can parse your json data with:
var array = JSON.parse(data);
and then you can get everything like this:
var refno = array["value"]["details"][0]["shipment_ref_no"];
you can parse like ...
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
NSDictionary *dictValue = [[NSDictionary alloc] initWithDictionary:[jsonDic objectForKey:#"value"]];
NSArray *arrDetails = [[NSArray alloc] initWithArray:[dictValue objectForKey:#"details"]];
for (int i=0; i<arrDetails.count; i++)
{
NSDictionary *dictDetails=[arrDetails objectAtIndex:i];
NSDictionary *dictContact = [[NSDictionary alloc] initWithDictionary:[dictDetails objectForKey:#"point_of_contact"]];
NSDictionary *dictProduct = [[NSDictionary alloc] initWithDictionary:[dictDetails objectForKey:#"products"]];
}
NSDictionary *response = //Your json
NSArray *details = response[#"value"][#"details"]
etc. Pretty easy
Update your code as follows. You are trying to read the details array from the top level whereas in your data its inside the value key. So you should read the value dict and within that read the details array.
NSString* pendingResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *jsonData = [pendingResponse dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
NSDictionary *valueDict = [jsonDic objectForKey:#"value"];
NSArray *argsArray = [[NSArray alloc] initWithArray:[valueDict objectForKey:#"details"]];
NSDictionary *argsDict = [[NSDictionary alloc] initWithDictionary:[argsArray objectAtIndex:0]];
NSLog(#"keys = %#", jsonDic[#"values"]);
I think your problem is that you have:
NSLog(#"keys = %#", jsonDic[#"values"]);
But it should be:
NSLog(#"keys = %#", jsonDic[#"value"]);
Below is code for parsing JSON array. i have used to parse JSON array from file but you can also do this using response link also.I have provided code for both and are below.
// using file
NSString *str = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"json"];
NSData *data = [[NSData alloc]initWithContentsOfFile:str];
NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSMutableDictionary *dictValues = [[NSMutableDictionary alloc]initWithDictionary:[dict valueForKey:#"value"]];
NSMutableArray *array = [[NSMutableArray alloc]initWithArray:[dictValues valueForKey:#"details"] copyItems:YES];
NSLog(#"Array Details :- %#",array);
// using url
NSURL *url = [NSURL URLWithString:#"www.xyz.com"]; // your url
NSData *data = [[NSData alloc]initWithContentsOfURL:url];
NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSMutableDictionary *dictValues = [[NSMutableDictionary alloc]initWithDictionary:[dict valueForKey:#"value"]];
NSMutableArray *array = [[NSMutableArray alloc]initWithArray:[dictValues valueForKey:#"details"] copyItems:YES];
NSLog(#"Array Details :- %#",array);

IOS/xcode debug crash handling json feed

IOS newb here having trouble with debugging.
Am trying to handle a json feed but code below is breaking at
- (void)viewDidLoad {
[super viewDidLoad];
shnote = #"shnote”;
lnote = #"lnote”;
myObject = [[NSMutableArray alloc] init];
self.title=#"Challenges";
NSData *jsonSource = [NSData dataWithContentsOfURL:
[NSURL URLWithString:#"http://www.~~/webservice.php"]];
id jsonObjects = [NSJSONSerialization JSONObjectWithData:
jsonSource options:NSJSONReadingMutableContainers error:nil];
for (NSDictionary *dataDict in jsonObjects) {
//BREAKS HERE
NSString *shnote_data = [dataDict objectForKey:#"shnote”];
//ABOVE LINE HIGHLIGHTED IN GREEN AT BREAKPOINT
NSString *lnote_data = [dataDict objectForKey:#"lnote”];
dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
shnote_data, shnote,lnote_data, lnote,nil];
[myObject addObject:dictionary];
}
/*
*/
}
The line highlighted in console is
dataDict = (NSDictionary *const)#"notes"
notes is name of table but other than that I am clueless.
Would appreciate any suggestions.
Your data source is of the format:
{
"notes": [
{
"row": {
"shnote": <...>,
"lnote": <...>
}
},
{
"row": {
"shnote": <...>,
"lnote": <...>
}
},
<...>
]
}
Steps to fetch each row content should therefore be:
Read value of notes property
Iterate through each row
Read value of row property
Read shnote and lnote properties
You're missing steps 1, 2 and 3. In code:
NSURL *url = [NSURL URLWithString:#"http://www.~~/webservice.php"];
NSData *jsonSource = [NSData dataWithContentsOfURL:url];
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:jsonSource options:NSJSONReadingMutableContainers error:nil];
NSDictionary *notes = jsonObject[#"notes"];
for(NSDictionary *note in notes) {
NSDictionary *row = note[#"row"];
NSString *shnote = row[#"shnote"];
NSString *lnote = row[#"lnote"];
NSLog(#"%#, %#", shnote, lnote);
}

Using NSArray and NSDictionary to access a JSON object without a root element

Here's an example of my data:
[
{
code: "DRK",
exchange: "BTC",
last_price: "0.01790000",
yesterday_price: "0.01625007",
top_bid: "0.01790000",
top_ask: "0.01833999"
}
]
I'm trying to retrieve the value for last_price by loading the contents of my NSDictionary into an Array.
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSDictionary *darkDict = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
self.darkPosts = [NSMutableArray array];
NSArray *darkPostArray = [darkDict objectForKey:#""];
for (NSDictionary *darkDict in darkPostArray) {...
But my json doesn't have a root element, so what do I do?
Additionally, when using the suggested answer, the output is ("...
- (void)viewDidLoad{
[super viewDidLoad];
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSDictionary *darkDict = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
NSString *lastP = [darkDict valueForKey:#"last_price"];
self.dark_label.text = [NSString stringWithFormat: #"%#", lastP];
}
It looks like you are wanting to iterate over your results. The root element is an array not a dictionary so you can just start iterating
NSError *error = nil;
NSArray *items = [NSJSONSerialization JSONObjectWithData:darkData
options:kNilOptions
error:&error];
if (!items) {
NSLog(#"JSONSerialization error %#", error.localizedDescription);
}
for (NSDictionary *item in items) {
NSLog(#"last_price => %#", item[#"last_price"]);
}
If you literally just want to collect an array of the last_price's then you can so this
NSArray *lastPrices = [items valueForKey:#"last_price"];
Convert the JSON to an NSArray with NSJSONSerialization. Then access the value:
NSData *darkData = [#"[{\"code\":\"DRK\",\"exchange\": \"BTC\",\"last_price\": \"0.01790000\",\"yesterday_price\": \"0.01625007\",\"top_bid\": \"0.01790000\"}, {\"top_ask\": \"0.01833999\"}]" dataUsingEncoding:NSUTF8StringEncoding];
NSArray *array = [NSJSONSerialization JSONObjectWithData:darkData
options:0
error:&error];
NSString *value = array[0][#"last_price"];
NSLog(#"value: %#", value);
NSLog output:
value: 0.01790000
If you are having trouble post the code you have written to get some help.
-- updated for new OP code:
The web service returns a JSON array or dictionaries not a JSON dictionary. First you have to index into the array and then index into the dictionary.
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSArray *darkArray = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
NSDictionary *darkDict = darkArray[0];
NSString *lastP = [darkDict valueForKey:#"last_price"];
NSLog(#"lastP: %#", lastP);
NSLog output:
lastP: 0.01970000
Note that the two lines:
NSDictionary *darkDict = darkArray[0];
NSString *lastP = [darkDict valueForKey:#"last_price"];
can be replaced with the single line using array indexing:
NSString *lastP = darkArray[0][#"last_price"];
Where the "[0]" gets the first array element which is a NSDictionary and the "[#"last_price"]" gets the names item from the dictionary.

Unrecognized selector sent to instance in JSON parsing

Please help me debug this code
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSError *error = nil;
NSURL *urls = [NSURL URLWithString:[NSString stringWithFormat:#"http://cnapi.iconnectgroup.com/api/UserProfile?id=1"]];
NSString *json = [NSString stringWithContentsOfURL:urls encoding:NSASCIIStringEncoding error:&error];
NSLog(#"JSon data = %# and Error = %#", json, error);
if(!error)
{
NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
NSArray *myJsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
NSLog(#"JSON data is :: %#", myJsonArray);
for(NSDictionary *jsonDictionary in myJsonArray)
{
//NSString *uids = jsonDictionary[#"UID"];
NSString *address1 = jsonDictionary[#"Address1"];
NSString *address2 = jsonDictionary[#"Address2"];
NSString *city = jsonDictionary[#"City"];
NSString *emailId = jsonDictionary[#"EmailID"];
NSString *fname = jsonDictionary[#"FName"];
NSString *fax = jsonDictionary[#"Fax"];
NSString *lname = jsonDictionary[#"LName"];
NSString *password = jsonDictionary[#"Password"];
NSString *phone = jsonDictionary[#"Phone"];
NSString *state = jsonDictionary[#"State"];
NSString *uids = [jsonDictionary objectForKey:#"UID"];
NSString *zip = jsonDictionary[#"Zip"];
NSString *company = jsonDictionary[#"company"];
NSString *department = jsonDictionary[#"department"];
NSLog(#"Uid is = %#", uids);
NSLog(#"First Name = %#", fname );
NSLog(#"Last Name = %#", lname);
NSLog(#"Company = %#", company);
NSLog(#"Email Id = %#", emailId);
NSLog(#"Password = %#", password);
NSLog(#"Department = %#", department);
NSLog(#"Address 1 = %#", address1);
NSLog(#"Address 2 = %#", address2);
NSLog(#"City = %#", city);
NSLog(#"State = %#", state);
NSLog(#"Zip = %#", zip);
NSLog(#"Phone = %#", phone);
NSLog(#"Fax = %#", fax);
}
}
});
[activity stopAnimating];
self.activity.hidden = YES;
}
Image will give you where the error is. I get this error after clicking stepover to debug. I also tried
NSString *address1 = [jsonDictionary objectForKey:#"Address1"];
From the output of url, it shows it's not array but a dictionary. You are trying to convert to array here.
NSArray *myJsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
instead use this
NSDictionary *myJsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
then remove that for loop no need of it. and replace your variable jsonDictionary with myJsonDictionary so to retrieve values.
// for(NSDictionary *jsonDictionary in myJsonArray)
Run now it will be fine. Worked for me fine
If the output was array of Dictionaries it would have been looked like this with square brackets around.
For Ex: [{"id": "1", "name":"Aaa"}, {"id": "2", "name":"Bbb"}]
If you are not sure of nature of response from url you can check for
the type. For ex:
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
if ([jsonObject isKindOfClass:[NSArray class]]) {
NSLog(#"its an array!");
NSArray *myJsonArray = (NSArray *)jsonObject;
// Handle Array of Dictionary
for(NSDictionary *jsonDictionary in myJsonArray)
{
NSString *address1 = jsonDictionary[#"Address1"];
//and so on
}
}
else {
NSLog(#"It's Dictionary");
NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
NSLog(#"jsonDictionary - %#",jsonDictionary);
//Handle NSDictionary
}
jsonDictonary is a NSString not as you expect NSDictonary.
Double check your JSON and maybe before calling that function check if it's NSDictonary.
Your should use one of the semi-standard frameworks for parsing JSON into Core Data. There are some SO questions about those.
In this case, your JSON has only one object which is not an array.
In general, your app shouldn't abort if server sent something unexpected, so it's better to use a parser which will loudly complain about malformed JSON than with it from scratch.

Json conversion problems: invalid characters found

I am converting my array to json object, then sending it to server. But It is showing some invalid characters when i get them in server end. like '\n', & '\'.
Here is a sample of my data which i get at the server end:
('[\n "{\\"id\\":2,\\"qrCode\\":\\"KdcUfeddHpbepeXnyiKFjcfedHp\\",\\"activity\\":\\"2\\",\\"time\\":\\"64485\\",\\"image_base64\\":\\"\\/9j\\/4AAQSkZJRgABAQAA"}"\n]');
But it should look like the following:
('[{"id":2,"qrCode":"KdcUfeddHpbepeXnyiKFjcfedHp","activity":2,"time":1372757846,"image_base64":"AA\\u003d\\u003d\\n"}]');
here is the code:
-(void)setOflynData2JsonFormat{
if (!([self.getOfflineData count] == 0)) {
NSArray *array = [self getOfflineData];
for (int i = 0; i<[array count]; i++) {
uniqueId++;
NSNumber *uId = [NSNumber numberWithInt:uniqueId];
OfflineTableObject *offObj = [array objectAtIndex:i];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:uId forKey:#"id"];
[dict setValue:offObj.qrCode forKey:#"qrCode"];
[dict setValue:offObj.offlineStatus forKey:#"activity"];
[dict setValue:offObj.time forKey:#"time"];
[dict setValue:offObj.imageData forKey:#"image_base64"];
SBJsonWriter *jsonWriter = [[SBJsonWriter alloc] init];
NSString *singleJsonString = [jsonWriter stringWithObject:dict];
NSLog(#"Json string : %#",singleJsonString);
arrayOfJsonString = [[NSMutableArray alloc]init];
[arrayOfJsonString addObject:singleJsonString];
}
NSData *jsonDataFromArray = [NSJSONSerialization dataWithJSONObject:arrayOfJsonString options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonDataFromArray encoding:NSUTF8StringEncoding];
NSLog(#"jsonData as string:\n%#", jsonString);
int check = [obj sendOfflynData2Server:jsonString];
}
}
So, where is the problem? Thnaks in advance for the help.
The problem is that you are translating your data to JSON twice.
You first translate all your dicts to json with
NSString *singleJsonString = [jsonWriter stringWithObject:dict];
add them to an array, and then re-translate the array to JSON with
NSData *jsonDataFromArray = [NSJSONSerialization dataWithJSONObject:arrayOfJsonString options:NSJSONWritingPrettyPrinted error:nil];
So instead of producing the expected JSON output, it serialize an array of JSON strings, hence the escaping mess.
Instead, you should just add your dicts to the array, and then serialize the whole thing :
arrayOfJsonString = [[NSMutableArray alloc]init];
for (int i = 0; i<[array count]; i++) {
// snip
[arrayOfJsonString addObject:dict];
}
NSData *jsonDataFromArray = [NSJSONSerialization dataWithJSONObject:arrayOfJsonString options:NSJSONWritingPrettyPrinted error:nil];

Resources