I'm parsing a Json object via AFJSONRequestOperation, the problem is, i cant get the correct value of the node.
The Json :
Link
I need to get only the temp value, inside the "results". I can get the results node, but the value inside it come as a array, how i can get the value for the name ?
That JSON is invalid. Go to this link, and check it.
What Snaker answered is pretty accurate, still:
for (NSDictionary *dic in results)
{
NSString *name = [dic objectForKey:#"name"];
}
Your problem here, is that the results gives you a dictionnary of dictionnaries.
So you have to retrieve the dictionnary called "results", and then, once you got all the dictionnaries in it, you look for the names trough a loop.
More information here
UPDATE :
dicionario = [dicionario objectForKey#"results"];
NSMutableArray *namesFromDict = [[NSMutableArray alloc] init];
for (NSDictionary *elts in dicionario)
{
[namesFromDict addObject:[elts objectForKey:#"name"]];
}
This should do.
Related
The basic gist: I've got some JSON coming back from a webservice to validate a login; that part works. I'm pulling values out of the array into an NSDictionary; that part works. I need to check one of the values that comes back to know if it was successful or not. That's where it's failing. And as far as I can tell, it's telling me that "success" is not equal to "success".
NSDictionary *jsonArray = [NSJSONSerialization JSONObjectWithData: response options: NSJSONReadingMutableContainers error: &err];
NSString *result = [jsonArray valueForKey:#"result"];
NSLog(#"%#",result);
if ([result isEqual:#"success"]) {
The log shows "result" is getting set as "success", but it never seems to evaluate as true.
If I set "result" manually:
NSString *result = #"success";
...it gets into the if statement just fine, so it seems like there's something I'm missing that's pointing to a data type or something similar... I'm just at a loss of what else to try at this point.
I'm normally a web dev, but I'm new to iOS, so my debugging is still a little lacking in xcode but I'm familiar with general logic and such. Any help you guys could give me would be fantastic!
Edit:
NSLog showing the JSON coming back from the webservice:
2014-01-10 16:22:42.568 LoginTest[1640:70b] (
{
code = 1;
fname = Joe;
lname = Tests;
result = success;
token = 2555f13bce42b14cdc9e60b923bb2b20;
vendornum = 50000000;
}
)
Edit - final working code:
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: response options: NSJSONReadingMutableContainers error: &err];
NSLog(#"jsonArray: %#", jsonArray);
NSString *result = [jsonArray[0] objectForKey:#"result"];
NSLog(#"%#",result);
if ([result isEqual:#"success"]) {
Earlier you commented (from a now removed answer) that -isEqualToString: threw an unrecognized selector. I believe it was -[__NSCFArray -isEqualToString:] or something very similar.
Based on your comment, you don't have "success", you have [ "success" ] in your JSON.
That is an array which wraps the value of a string. You need to get the first element of the array and use that.
[result[0] isEqual:#"success"]
Based on the output in your log, your JSON is not an object
{
…
"result" = "success"
…
}
It is an array with only one object in it.
[
{
…
"result" = "success"
…
}
]
You are working with an array of data so the output of -valueForKey: will be an array of data.
#MartinR is correct, it may be clearer to use
[jsonArray[0] objectForKey:#"result"]
to get the result.
You didn't show us the actual output of the log. That's bad. Deducing from your comments, it should have shown something like
(
"success"
)
which is the description of an array object (NSArray) containing a string, rather than the string object itself.
If this is indeed the case, then you need to get the (only? first?) element in the array and compare that using isEqual: or isEqualToString:.
if we want to compare two NSString we use [str1 isEqualToString:str2]; You should do same instead of isEqual:
isEqual: compares a string to an object, and will return NO if the object is not a string. do it if you are not sure if object is NSString.
`isEqualToString:` use it when you are sure both Objects are NSString.
I have a json structure like this
I am trying to check for the "type" in each nested widgets array.So if it is of a certain type then i am trying to extract properties like fade steps,width, height etc.
Is there a way of doing it using the for loop?
Right now I am doing like this:
for (NSString *widgetArray in widgets)
{
NSLog(#"%#", widgetArray);
}
Its printing the contents, How do I extract corresponding values?
for(NSDictionary *asset in [assets allValues])
{
NSString *type = asset[#"type"];
if ([type isEqualToString:#"gradient"])
{
[gradients addObject:asset];
}
This is the pseudo code provided by one of the members which helped me access the contents of the dictionary, I am not able to apply a similar logic to the nested array structure.
Since the problem is recursive search, you have to use stack. Here are the steps:
Create NSMutableArray that will serve as the stack. Now it is empty.
Take the root widgets array and put all its objects onto the stack (-addObjectsFromArray:).
Take out the first widget (NSDictionary) in stack. Be sure to take it out of the stack (-removeObjectAtIndex:) after storing it in variable.
Do your type comparision and other stuff with that variable.
Take its subwidgets and put all of them onto the stack just like in step 2.
If the stack has something in it, repeat from step 3. Otherwise you processed all widgets.
Pseudo code:
// 1
NSMutableArray *stack = [NSMutableArray array];
// 2
[stack addObjectsFromArray:rootWidgets];
while (stack.count > 0) {
// 3
NSDictionary *widgetDict = [stack objectAtIndex:0];
[stack removeObjectAtIndex:0];
// 4
if ([[widgetDict objectForKey:#"type"] isEqualToString:...]) // Do whatever...
// 5
[stack addObjectsFromArray:[widgetDict objectForKey:#"widgets"]];
}
// 6
// You are done...
To check the type of each element, use the NSObject isKindOfClass: method.
So, you might have something like:
if ([obj isKindOfClass:[NSDictionary class]]) { ... }
Or
if ([obj isKindOfClass:[NSArray class]]) { ... }
Like #H2CO3 says, you use objectAtIndex: to access array elements and objectForKey: to access dictionary elements.
EDIT: I just realized that by "of a certain type" the OP meant the value of the "type" field, rather than the objective-c class of an entry. Still, it is often useful when reading JSON data to determine whether an entry is an array or dictionary, so I will leave my answer here.
In the latest objective C you can use subscripting like C arrays. For example,
NSLog(#"%#", widgetArray[i]);
For dictionaries you can extract via key:
NSString* id = myDict[#"id"];
I'm working on a piece of code that GETs a URL and parses the contents for data between a asset of tags. In this case, it's looking for the code between and . When the URL body returned doesn't contain those tags, the cullXML: method returns an empty array like this:
return [NSArray arrayWithObjects: nil];
I check to be sure that the returned array has objects with:
if ( matchesXML.count ) {
In my debug code, I check twice. The first time, it works fine. The second time, just a couple lines later, it crashes. I can't see why. The lines look the same to me.
What am I missing?
A bigger chunk of the code is included below. Thanks!
if (self.newResults) {
NSString *urlResult;
NSArray *matchesXML;
NSArray *match;
NSDictionary *currentResult;
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
NSArray *returnedObjects;
NSArray *dictionaryKeys;
NSMutableArray *currentResultObjects;
int i = 0;
// determine tournament type, because the fields are different per type
NSString *tournamentType;
tournamentType = [[AFMethods tournamentTypeFromId:self.inputTournamentId] objectAtIndex:0];
urlResult = [NSString stringWithFormat:#"%#", responseHandle];
[responseHandle release];
NSLog(#"urlResult retrieved: %#", urlResult);
matchesXML = [AFMethods cullXML: urlResult forTag: #"matches"];
NSLog(#"matches loaded: %#", matchesXML);
NSLog(#"matchesXML.count %i", matchesXML.count);
if ( matchesXML.count ) {
NSLog(#"not nil");
}
NSLog(#"just before tested");
if ( matchesXML.count ) {
NSLog(#"tested");
I found the issue!
It wasn't crashing where I thought. It was a couple lines later. I was releasing an auto-released object. It must have been a left-over line from a previous organization of the code.
I removed the release and it's working perfectly again.
My guess is that you're not using the return statement you listed, but rather one that returns a different NSArray, only this one isn't retained. The first NSLog causes heap to be used, stomping on the array object.
I have a simple object. It has several NSString properties (propertyA, propertyB, propertyC).
I have a string (read from a csv file) in the following form:
this is value A, this is value B, this is value C
another row A, another row B
Notice that the second row is missing the last property.
I want to parse the string into my object. Currently I'm grabbing a line from the csv file and then doing this:
MyObject *something = [[MyObject alloc] init];
NSArray *split = [line componentsSeparatedByString:#","];
if (something.count > 0)
something.propertyA = [split objectAtIndex:0];
if (something.count > 1)
something.propertyB = [split objectAtIndex:1];
if (something.count > 2)
something.propertyC = [split objectAtIndex:2];
This works well, but feels really horrible and hacky!
Has anyone got any suggestions for how I can improve the code?
Take a look at this tread about parsing CSV Where can I find a CSV to NSArray parser for Objective-C?
Dave DeLong wrote a CSV-parser library, you can find it here: https://github.com/davedelong/CHCSVParser
Hope this helps :)
Here's a CSV parsing extension to NSString that I used in the past to handle CSV data.
http://www.macresearch.org/cocoa-scientists-part-xxvi-parsing-csv-data
If basically adds a -(NSArray *)csvRows method to NSString that returns a NSArray with each row on your data and a NSArray inside each row to handle the columns.
It's the simplest and cleanest way I found so far to deal with the ocasional CSV data that comes up.
Your approach actually seems pretty sound, given the input format of the file, and assuming that no individual items actually contain a comma within themselves. As others have mentioned, CSV and/or custom flat files require custom solutions to get what you want from them.
If the approach above gets you the data you want, then I say use it. If it doesn't though, perhaps you can share the actual problem you're experiencing (ie, what data are you getting out, and what were you expecting?)
Consider using an array of keys that correspond to MyObject property names. For example:
NSString *propertyNames[] = { #"property1", #"property2", #"property3" };
NSArray *values = [line componentsSeparatedByString:#","];
NSArray *keys = [NSArray arrayWithObjects:propertyNames count:[values count]];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:values forKeys:keys];
MyObject obj = [[MyObject alloc] init];
[obj setValuesForKeysWithDictionary:dict];
You could then consider adding an initWithDictionary: method to MyObject that calls setValuesForKeysWithDictionary. That would help streamline things a little further, allowing you to write the last two lines above as a single line:
MyObject obj = [[MyObject alloc] initWithDictionary:dict];
I have to parse an XML file using NSXMLParser. There are so many HTML tags in them, so when I am trying to parse it, it will store the string up to that and then again go to found character method and starts to append it.
my code is:
if (Bio_CResults) {
[BioResults appendString: string];
[Info appendString:string];
[stringarr addobject:Info];
NSLog(#"bio==%#",BioResults);
NSLog(#"string==%#",string);
}
and I want to add it in string array, but here it will make create extra object of array. i.e.
stringarr objectAtIndex 0 = abc
stringarr objectAtIndex 1 = def
stringarr objectAtIndex 2 = ghi
but actually I want all of them together in one object because they are actually one string only..
plz help me for that
If you don't even need multiple string objects you can use an NSMutableString instead of an array. Just use the appendString: method to add to the end of the string:
NSMutableString *string = [NSMutableString string];
[string appendString:#"abc"];
[string appendString:#"def"];
NSLog(#"New string is %#", string);
This will log "New string is abcdef".
If you really want an array, use an NSMutableArray instead of an NSArray. That way you can change an object in-place (replace a string with a new string created by appending another string). So for example:
// First create an array with #"abc"
NSMutableArray *mArray = [NSMutableArray arrayWithObject:#"abc"];
// Next get the first object as a string and append #"def" to it in-place
NSString *string = (NSString *)[mArray objectAtIndex:0];
[mArray replaceObjectAtIndex:0 withObject:[string stringByAppendingString:#"def"]];
// Now get the new first object
NSLog(#"First object is %#", (NSString *)[mArray objectAtIndex:0]);
This will log the message "First object is abcdef".
I really dont like NSXmlParser. You might want to read my blog post on using RegxKitLite
http://blog.bluespark.co.nz/?p=51
It might be of some help. Hopefully it wont lead you in the wrong direction.
Cheers, John.
There are so many HTML tags in them…
Be aware that HTML is usually not valid XML. If you're parsing HTML, an XML parser will throw an error some part of the way through the document.
You may be better off creating a WebView, loading the HTML content into it, and then getting a DOMDocument from the view's main frame and traversing the DOM hierarchy. You don't have to put the view into a window; you can just use it to get a DOMDocument.
If you are parsing XML and meant to say “XML tags”, you can disregard this answer.