IOS/xcode debug crash handling json feed - ios

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);
}

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);

JSON file in arrays

I'm trying to parse this JSON :
[
{
"text" : "Test",
"color" : "yellow",
},
{
"text" : "Test2",
"color" : "blue",
},
]
I am trying to get two arrays, one with the key "text" and another with the key "color".
NSString *jsonPath = [[NSBundle mainBundle] pathForResource:#"notes"
ofType:#"json"];
NSError *e = nil;
NSData *data = [[NSData alloc] initWithContentsOfFile:jsonPath];
NSArray *parsed = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&e];
if (! [parsed isKindOfClass:[NSArray class]]) {
NSLog(#"Error");
}
NSArray *texts = [[NSMutableArray alloc] init];
NSArray *colors = [[NSMutableArray alloc] init];
for (NSDictionary* dict in parsed)
{
[texts addObject:dict [#"text"]];
[colors addObject:dict [#"color"]];
}
I have an error with the following code:
[texts addObject:dict [#"text"]];
[colors addObject:dict [#"color"]];
How should I fix this?
Looking at your JSON data, you've got an array that contains 2 dictionaries. Each dictionary has keys for text and color.
You can use a trick on the array to get all the values in one:
First, your code to extract the JSON into an NSArray:
NSString *jsonPath = [[NSBundle mainBundle] pathForResource:#"notes"
ofType:#"json"];
NSError *e = nil;
NSData *data = [[NSData alloc] initWithContentsOfFile:jsonPath];
NSArray *parsed = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&e];
Now the trick:
NSArray *textEntries = [parsed valueForKey: #"text"];
NSArray *colorEntries = [parsed valueForKey: #"color"];
EDIT:
The trick is in sending the valueForKey message to an array. When you do that, it passes on the message to every object in the array. The array then builds a new array with the answer it gets back from each object it contains and returns the resulting array to you. This does a whole lot of work for you with a very simple statement.

Store JSON output in NSArray

Good morning,
I'm trying to develop my first App and I'm using TableView in order to show my entries from a MySQL database and I'm having some trouble when I have to parse the JSON output.
I have already created the connection with my JSON, but now I need to save all the id in a single Array, all the user in another array, etc, etc. As you can see below in my second code, I need to store them in a NSArray. How can I do that?
That's my JSON
[{"id":"15","user":"1","imagen":"http:\/\/farmaventas.es\/images\/farmaventaslogo.png","date":"2014-09-13"}
,{"id":"16","user":"2","imagen":"http:\/\/revistavpc.es\/images\/vpclogo.png","date":"2014-11-11"}]
And that's my TableViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSString * urlString = [NSString stringWithFormat:#"http://website.com/service.php"];
NSURL * url = [NSURL URLWithString:urlString];
NSData * data = [NSData dataWithContentsOfURL:url];
NSError * error;
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
// Here I have to store my "user"
self.carMakes = [[NSArray alloc] initWithObjects: nil];
// Here I have to store my "imagen"
self.carModels = [[NSArray alloc] initWithObjects: nil];
}
Thanks in advance.
That's another solution with KVC
NSArray *carMakes = [json valueForKeyPath:#"#unionOfObjects.id"];
NSArray *carModels = [json valueForKeyPath:#"#unionOfObjects.user"];
First of all, you would want to fetch JSON on another thread, so you dont block your main thread with it:
#interface ViewController ()
#end
#implementation ViewController
-(void)viewDidLoad
{
[super viewDidLoad];
[self fetchJson];
}
-(void)fetchJson {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSString * urlString = [NSString stringWithFormat:#"http://website.com/service.php"];
NSURL * url = [NSURL URLWithString:urlString];
NSData * data = [NSData dataWithContentsOfURL:url];
NSError * error;
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
// I advice that you make your carModels mutable array and initialise it here,before start working with json
self.carModels = [[NSMutableArray alloc] init];
#try {
NSError *error;
NSMutableArray* json = [NSJSONSerialization
JSONObjectWithData:theData
options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
error:&error];
if (error){
NSLog(#"%#",[error localizedDescription]);
}
else{
for(int i=0;i<json.count;i++){
NSDictionary * jsonObject = [json objectAtIndex:i];
NSString* imagen = [jsonObject objectForKey:#"imagen"];
[carModel addObject:imagen];
}
dispatch_async(dispatch_get_main_queue(), ^{
// If you want to do anything after you're done loading json, do it here
}
});
}
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
// Here you have to store my "user"
self.userArray = [[NSMutableArray alloc]init];
for (NSDictionary *userInfo in json){
//get "user" from json
NSString* user = [userInfo objectForKey:#"user"];
//add to array
[userArray addObject:user];
}
You have use NSMutableArray to add object instead.
Since "json" is array of NSDictionary you can get iterate over it and add to arrays like this:
NSArray *json = #[#{#"id":#"15",#"user":#"1",#"imagen":#"http:\/\/farmaventas.es\/images\/farmaventaslogo.png",#"date":#"2014-09-13"},
#{#"id":#"16",#"user":#"2",#"imagen":#"http:\/\/revistavpc.es\/images\/vpclogo.png",#"date":#"2014-11-11"}];
NSArray *carMakes = [NSArray array];
NSArray *carModels = [NSArray array];
for (NSDictionary *dict in json) {
carMakes = [carMakes arrayByAddingObject:dict[#"id"]];
carModels = [carModels arrayByAddingObject:dict[#"user"]];
}
NSLog(#"%#",carMakes);
NSLog(#"%#",carModels);

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.

Parsing a JSON array with dictionaries

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);

Resources