I am trying to send JSON data in matchData object when a user end its turn. If I check the json before sending it is valid and looks like,
JSON:
{
"p1score" : "0",
"turn" : "0",
"pb1" : "BPS1120|2231|3422|4213|5244|6135",
"player2" : "0000177110",
"player1" : "0000177110",
"p2score" : "0",
"movements" : "MVS2242",
"pb2" : "BPS1630|2511|3522|4543|5534|6625",
"moves" : "30"
}
Prepares the data for sending,
NSData *matchData = [[NSString stringWithFormat:#"%#",realMatchData] dataUsingEncoding:NSUTF8StringEncoding];
realMatchData contains the above json string.
But if convert the matchData back to string again to check what is being sent using,
NSString *str = [[NSString alloc] initWithData:matchData encoding:NSUTF8StringEncoding];
I get back the following json string
{
"moves" : "30",
"turn" : "0",
"player2" : "G:0000177110",
"p1score" : "0",
"player1" : "G:0000177110",
"movements" : "MVS",
"p2score" : "0"
}
keys pb1 and pb2 are missing.
I event tried to pass the values of pb1 and pb2 as nested json but problem remains the same, they keys are missing when sending data.
Is the right way to share the game state or should I use some other approach to share data ?
Thanks.
This does not answer the question exactly, but it may solve the problem, and the asker asked for an example. Apple provides its own JSON serialization which produces an NSData object from JSON serializable objects like NSNumber, NSArray, NSString, NSDictionary, etc.
NSMutableArray* matchArray = [NSMutableArray array];
/*
Fill the match array with the appropriate objects to represent your game state...
You've presumably already done this in order to get that string object...
*/
NSData* matchData = [NSJSONSerialization dataWithJSONObject: matchArray
options: 0 //pretty sure all the options here are irrelevant for our purposes
error: NULL]; //pass in a pointer to an NSError if you are interested in the error
//end the turn or do whatever one does in a non-turn-based match with matchData as the data object
Related
I am developing simple app in iOS that gets data web api my code returned json data correctly but when I want to specific for example student name from json returned null.
Here is my data :
{
Sudent(
{
{"id":"20",
"name":"Alan",
"email":"simpl#gmail.com",
"phone":"1234567890",
"location":"London"},
{
"id":"40",
"name":"John",
"email":"simpl#gmail.com",
"phone":"1234567890",
"location":"usa"},
"id":"50",
"name":"Nora",
"email":"simpl#gmail.com",
"phone":"1234567890",
"location":"kenya"},
})}
Here my code that gets data as json and stored NSMutableArray named Student:
-(void)proxydidFinishLoadingData:(id)data InMethod:(NSString*)method
{
if ([method isEqualToString:#"getstudentdata"]){
defaultDict = [[NSMutableDictionary alloc]init];
[defaultDict addEntriesFromDictionary:[NSJSONSerialization JSONObjectWithData:[data dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]];
Student = [defaultDict objectForKey:#"data"];
}
}
this codes it works ok and correctly and returned json data but the problem is when I want to get specific index such as names of students it is not work it returns null value.
the code that does this work is here:
NSMutableDictionary *response = [[defaultDict valueForKey:#"data"] mutableCopy];
NSString *name = [[response valueForKey:#"name"]];
];
NSLog(#"%#" ,name);
Please help me this to get student names
You are checking "name" key in "data" key, but in fact it is present in "Student" key.
Parse to Student object and using for loop get one by one "name" key value.
Use this site http://www.json4swift.com/ to create Model.(Just you have to Put JSON response here).
Var dataModelArray = [Your_Model_Type]()
if let data = data[“student”] as? [String: AnyObject] {
dataModelArray = Your_Model_type.modelsFromDictionaryArray(array: data)
}
//And you will have array of data in your dataModelArray
//Example you can access like this
dataModelArray[0].name
So I was working on a project that required me to work with some JSON, I was running into a few issues regarding the best way of representing things. First of, this is how the JSON looks:
"phoneList": [
{
"phoneReason": "End of Contract",
"phoneType": [
{
"id": 5,
"phoneType": "Android Smartphone"
}
]
}
]
I want to know the most appropriate way of representing this.
For example, I do know that that my phoneReason will just be a simple NSString while my phoneType is actually a NSArray. However,I wasn't sure how to represent a)the id, I know this is an integer, but should this be an NSInteger or an NSNumber and b)could someone point me in the direction of some sample code where I can understand how to model a dictionary object containing an integer and a string and also where I can understand how to model an array of dictionaries.
My other question is also similar in that say I'm actually posting something, how do I model this, specifically say for like dictionary type (JSON Curly Brace)objects that contain a number/integer and a string.
For example, this is the JSON I'm trying to model and then do something like this:
"phoneReason": "Upgrade",
"phoneInfo": {
"id": "2"
},
//And then I want to pass ID
-(void) createOurRequest:(NSNumber *)id {
NSDictionary *myDictionary = #{
#"phoneReason" : [NSString stringWithFormat:#"%i", s elf.dat.reason],
//How do I then represent the phoneInfo element exactly?
};
Sorry, for the clumsy question, would really appreciate any guidance on modeling JSON in iOS or just generally.
I'm assuming you're asking questions a) and b), and also how to model a JSON.
a) The unfortunate thing with Obj-C is that all collection elements have to be objects. Integers are value types, so they will need to be converted to NSNumbers to work. However, if you're parsing a JSON string, the builtin JSON parser does it for you. I'll describe it below.
b) The model is based on the JSON. You describe the object collection and the parser will determine the model for you. In your example, you would have a NSDictionary<NSString *: NSArray<NSDictionary<NSString *: id>*>*>. The innermost element has value of id because you can either have an NSString ("End of Contract") or an NSArray ("phoneType": [ { "id": 5, "phoneType": "Android Smartphone" } ])
Of course, the model is defined by your JSON, so if you run it through a parser, you get a structured object. You can access each element based on your model (object[#"phoneList"][#"phoneReason"]).
The class method to use is:
+ (id)JSONObjectWithData:(NSData *)data
options:(NSJSONReadingOptions)opt
error:(NSError **)error
Where you pass it a NSData representation of your string, options (or 0), and a NSError pointer (error*). You get back a parsed JSON with the proper structure you defined.
NSDictionary *parsedJSONObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:NULL
I have no options to use and I know there will be no error, so I pass nothing for those parameters. The resulting object will be in whatever structure your JSON is.
Using the objects and the json layout you provided in your first example, this is how I would go about creating the dictionaries and arrays to get the json in the format you specified. Hopefully this helps make it a little clearer for you.
// example constructor method
-(void) jsonStringWithPhoneReason:(NSString*)reason phoneId:(NSInteger)phoneId phoneType:(NSString*)phoneType
{
// create device detail dictionary
NSDictionary *deviceOneDetail = #{
#"id" : #(phoneId), // <- set phone id as NSNumber
#"phoneType" : phoneType // <- set your string phone type
};
// create device dictionary
NSDictionary *deviceOne = #{
#"phoneReason" : reason, // <- set your phone reason string
#"phoneType" : #[deviceOneDetail] // <- set your phone type dictionary within an array
};
// create phone list dictionary with any device dictionaries you want to add
NSDictionary *phoneListDict = #{
#"phoneList" : #[
deviceOne, // <- add your device to the phone list array of dictionaries
// deviceTwo...
]
};
NSString *jsonString = [self convertToJsonString:phoneListDict]; // <- convert the dictionary into a json string and use however you wish
// your json string should now look like this assuming you pass 'End of Contract', 5 & 'Android Smartphone' as arguments to this method
// {"phoneList":[{"phoneReason":"End of Contract","phoneType":[{"id":5,"phoneType":"Android Smartphone"}]}]}
}
-(NSString*) convertToJsonString:(NSDictionary*)dictionary
{
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary
options:0 // Pass 0 if you don't care about the readability of the generated string
error:&error];
if (error)
{
NSString *errorDesc = [NSString stringWithFormat:#"Error creating json data from dictionary: %#", error.localizedDescription];
NSLog(#"ERROR: %#", errorDesc);
jsonData = nil;
return nil;
}
NSString *returnString = nil;
if(jsonData != nil)
{
returnString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
return returnString;
}
I try to send data to the server. Server waits from my this structure among other:
{
...
"card": [
{
"child": {...},
"parent":{...}
},
{
"child": {...},
"parent":{...}
}
],
[...],
[...]
}
So it should be Dictionary ({...}) placed into another Dictionary ({"child":..., "parent":...}), placed into an Array ("card": []), and this array is a cell, the final API JSON contains many of such cells.
I realize this structure by something like this:
NSDictionary *card = #{#"key1" : #"val1", #"key2" : #"val2", #"key3" : #"val3"};
NSDictionary *pair = #{#"parent" : card, #"child" : card};
NSArray *cards = [NSArray arrayWithObjects: pair, pair, nil];
After this I add cards Array into Dictionary with other auth data and send it to the server:
[self.userAuthData setObject: cards forKey:#"card"];
And I see in the server logs that data was shredded: http://monosnap.com/image/UbLPA0AK0eotAvG12o1ML4702xy0aj.png
But, if I use Dictionary cards instead of Array cards, everything is ok: http://monosnap.com/image/IzenpFc3Gik01UYhyRYtGFHmxBpCpC.png
What's wrong with idea to store Dictionary in an Array? Why it gets shredded?
Ok, answer is here: AFNetworking posts JSON arrays as multiple single-entry dictionaries
I just added a line in my ApiClient.m
_sharedClient.requestSerializer = [AFJSONRequestSerializer serializer];
I'm trying to transform a very simple JSON in to a NSDicationary to then populate my CoreData model with the retrieved data, the problem is after I get my json from the server and try to parse it to a NSDicationary my dictionary just show I have 811 values inside but they all are empry values.
I have printed my json (NSData) and all the content is there and my error var is null after this point.
This is the piece of code I use to do the parse:
[NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error]
And here is an example of my JSON:
[
{
"product": "A",
"name": "B"
},
{
"product": "B",
"name": "A"
}
]
If I print the data using the code below, the result is exactly the same I get from my server:
[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]
After clicking in the "I" (information) icon I got that:
Execution was interrupted, reason: Attempted to dereference an invalid
ObjC Object or send it an unrecognized selector. The process has been
returned to the state before expression evaluation.
But can't understand why...
I have already searched for this on stackoverflow and I didn't find any solution to my problem, maybe I'm searching with the wrongs terms.
You say you are parsing your JSON into an NSDictionary but the top-level data structure of your JSON is an array. Parse your JSON into an NSArray; each element of this array will be an NSDictionary.
I have the following situation:
NSDictionary *params = #{
#"Checkout" : #{
#"conditions" : #{#"Checkout.user_id" : #1},
#"order" : #{#"Checkout.id" : #"DESC"}
},
#"PaymentState" : #[],
#"Offer" : #[]
};
This dictionary contains params for a webservice request passing a JSON string with the webservice URL. I get the JSON string using NSJSONSerialization class, like this:
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
The problem is: jsonString "keys" is ordered differently from the original params dictionary keys order, like this:
{
"Offer":[],
"PaymentState":[],
"Checkout":{
"conditions":{"Checkout.user_id":6},
"order":{"Checkout.id":"DESC"}
}
}
That is, the "PaymentState" and "Offer" keys come first in jsonString, and i need maintain
the original order. This is very important, like this:
{
"Checkout":{
"conditions":{"Checkout.user_id":6},
"order":{"Checkout.id":"DESC"}
},
"Offer":[],
"PaymentState":[]
}
So guys, how can i do that??
I use OrderedDictionary from CocoaWithLove whenever I need to keep the order of my dictionary keys.
Basically, OrderedDictionary contains an NSMutableDictionary and an NSMutableArray for the keys inside it, to keep track of the order of the keys. It implements the required methods for subclassing NSDictionary/NSMutableDictionary and just "passes" the method call to the internal NSMutableDictionary.
According to the JSON spec a JSON object is specifically unordered. Every JSON library is going to take this into account. So even when you get around this issue for now, you're almost certainly going to run into issues later; because you're making an assumption that doesn't hold true (that the keys are ordered).
While NSDictionary and Dictionary do not maintain any specific order for their keys, starting on iOS 11 and macOS 10.13, JSONSerialization supports sorting the keys alphabetically (see Apple documentation) by specifying the sortedKeys option.
Example:
let data: [String: Any] = [
"hello": "world",
"a": 1,
"b": 2
]
let output = try JSONSerialization.data(withJSONObject: data, options: [.prettyPrinted, .sortedKeys])
let string = String(data: output, encoding: .utf8)
// {
// "a" : 1,
// "b" : 2,
// "hello" : "world"
// }