How to retain order of JSON data retrieved with AFNetworking? - ios

I am using AFNetworking to retrieve JSON data from a web service. Part of the response string I get is:
{"DATA":{"LEASE TYPE":"3 Yrs + 0 renew of 0 Yrs","LANDLORD":"","TENANT":"test comp"...
and so on. The order of the key values in the "DATA" dictionary ("LEASE TYPE","LANDLORD","TENANT"...) is important for presentation purposes. However, when AFNetworking calls NSJSONSerialization's:
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
method, the returned dictionary has the keys in a different order.
I notice that the AFJSONRequestOperation object has the server's response stored as an NSString, with everything in the correct order. However I'm not keen on parsing the JSON by hand if I can avoid it.
Can anyone suggest a way that will let me get at / keep the keys in their original order?
Thanks.

If the order is important use an array not a dictionary, dictionaries are be by their nature unordered. Or add an array of dictionary keys in the order desired.
If you have no control over the response that is sent you will have to parse the JSON yourself at least for the ordering.

When you'r creating an NSDictionary, the order will not be the same. I often recognized that dictionaries get ordered by key-name alphabetically.
But when using dictionaries the order doesn't really matter. And they shouldn't!

As the previous answers mentions dictionaries are by nature without order, but you can find here a nice class of OrderedDictionary:
http://www.cocoawithlove.com/2008/12/ordereddictionary-subclassing-cocoa.html
http://projectswithlove.com/projects/OrderedDictionary.zip

Related

Rearrange the order of keys in NSDictionary for crypto hash match of entire dictionary

Here is what I'm trying to achieve.
I have a payload in the below format.
//Ordered Payload - observed at the receiving end.
{
"xx":"First",
"yy":"Second",
"11":{
"xx1":"innerVal1",
"xx2":"innerVal2"
}
}
Since NSDictionary is basically unordered, it kinda shuffles this key - value pairs with in the dictionary when viewing on console of Xcode.
The same payload order is captured(as above ordered dict) when making a POST request at the api proxy end.
To ensure that the payload isn't tampered I need to do a hash(HMAC) of the payload and attach it in the request. The problem is that when I hash the payload (converting NSDict to JSON string) as is unordered just as NSDict property, and it won't match at the proxy when it tries to compares the hash with that of the ordered payload received in the request.
When I do a 'po' on NSDictionary this is what I see and its the same every time.
//unOrdered Payload - observed at the sending end.
//observe that the key holding a dictionary is always seen first in the dictionary followed by the other key-value pairs.
{
"11":{
"xx2":"innerVal2",
"xx1":"innerVal1"
},
"yy":"Second",
"xx":"First"
}
Is there any way I could make sure that my hash's are the same when the payload is not tampered ?
I understand its clearly not so possible, I think its worth giving a shot.
I have come up with other logic to use directly the key-value pairs for hashing and not the complete dictionary.
But since the payload format could be changing over the time, I don't want to keep changing the code at both client and server side for it.
Appreciate your time to help me find a solution for it.
Just hash the JSON data prior to sending, not the dictionary.
Convert the NSDictionary to JSON data with NSJSONSerialization method: dataWithJSONObject.
Hash the JSON data.
Sent the JSON data and hash.
On the server side:
Hash the received JSON data
Compare the computed hash to the received hash value
If hasing the JSON data is not an option just hash all the keys and values together or perhaps just the values if the keys are not an issue. Sort the keys and use that key order for hashing order.
Or just use SSL.

RestKit : How to parse the JSON response to NSDictionary without mapping any entity or class?

I just want the RestKit to parse the JSON data into NSDictionary, but not a class. This is because the attributes of the JSON data is dynamic, means the number of fields is not fixed and field count can be large. So I don't want to create a huge class to map the json data. Just keep that in NSDictionary. Does RestKit provide this functionality or we have to work out some other way.Guidance Needed.
Thanks.
Have to modify the Restkit to support the ability ....
RKObjectRequestOperation.HTTPRequestOperation.responseData
then parse the json data to dictionary or array
Either use AFNetworking (which RestKit is built on top of) or use a dynamic mapping (depending on your destination class needs).
If you have large arbitrary data then you should just avoid using RestKit as it will only slow your performance.

How to prevent order changing in NSDictionary in ios

Hi In my application I have a login screen where I have to post credentials to C# server.The order which I used is as such below
username
password
domainname
Code:
NSDictionary*disPost=[[NSDictionary alloc]initWithObjectsAndKeys:#"naresh",#"UserName",#"n123",#"Password",#"naresh-in",#"DomainName",nil];
I can able to post the data to server successfully but the credentials order is changing like below.
Password
UserName
DomainName
Due to this reason I am getting an exceptional error from server. Please help me to resolve this issue as soon as possible.
NSDictionary has key-value pairs, it is not ordered. You need an array to keep the order of the elements. You could use 2 arrays (1 for keys the other for values) or use an array for keys (to know the order) and a dictionary for the key-value pairs.
NSDictionary is not an ordered container. If you really want an ordered dictionary then use OrderedDictionay from,
http://www.cocoawithlove.com/2008/12/ordereddictionary-subclassing-cocoa.html
Your question makes me think that its not NSDictionary that you want to use, because with dictionaries you really shouldn't care about the order.
And I think the glitch in your code is probably with the part that sends to the server, try sending them separately, or use another datatype than NSDictionary.
good luck!

Restkit mapping an array of strings

Using Restkit in my iOS project and the api is getting back a generic array of strings. How do I get access to those array of strings?
This is what is returned by the api.
{
"servers": ["http://myserver.com", "http://myotherserver.com"]
}
Assuming the response is an NSDictionary:
strings = [{response_object} objectForKey: #"servers"]
Will return an NSArray of the strings held in the servers key.
Replace {response_object} with whatever your response is. I may not be understanding your question though, it's quite vague.

NSDictionary Vs. NSArray

I am reading on objective-c (a nerd ranch book), and I can't help thinking about this question: How do I decide which collection type, NSArray or NSDictionary (both with or w/o their mutable subclasses), to use when reading content from URL?
Let's say am reading JSON data from a PHP script (a scenario am dealing with), which to use? I know it is stated in many references that it depends on structure of data (i.e. JSON), but could a clear outline of the two structures be outlined?
Thank you all for helping :)
NSArray is basically just an ordered collection of objects, which can be accessed by index.
NSDictionary provides access to its objects by key(typically NSStrings, but could be any object type like hash table).
To generate an object graph from a JSON string loaded via a URL, you use NSJSONSerialization, which generates an Objective-C object structure. The resulting object depends on the JSON string. If the top-level element in your JSON is an array (starts with "["), you'll get an NSArray. If the top-level element is a JSON object (starts with "{"), you'll get an NSDictionary.
You want to use NSArray when ever you have a collection of the same type of objects, and NSDictionary when you have attributes on an object.
If you have, lets say a person object containing a name, a phone number and an email you would put it in a dictionary.
Doing so allows the order of the values to be random, and gives you a more reliable code.
If you want to have more then one person you can then put the person objects in an array.
Doing so allow you to iterate the user objects.
"withContentOfURL" or "withContentOfFile" requires the data in the URL or the file to be in a specific format as it is required by Cocoa. JSON is not that format. You can only use these methods if you wrote the data to the file or the URL yourself in the first place, with the same data. If you write an NSArray, you can read an NSArray. If you write an NSDictionary, you can read an NSDictionary. Everything else will fail.

Resources