Assigning a dictionary to a variable - ios

When check self.weatherData, I get nothing even though there is data in "data". Here is my function:
- (void)handleNetworkResponse:(NSData *)myData
{
//NSMutableDictionary *data = [NSMutableDictionary dictionary];
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
// now we'll parse our data using NSJSONSerialization
id myJSON = [NSJSONSerialization JSONObjectWithData:myData options:NSJSONReadingMutableContainers error:nil];
// typecast an array and list its contents
NSDictionary *jsonArray = (NSDictionary *)myJSON;
// take a look at all elements in the array
for (id element in jsonArray) {
id key = [element description];
id innerArr = [jsonArray objectForKey:key];
NSDictionary *inner = (NSDictionary *)innerArr;
if ([inner conformsToProtocol:#protocol(NSFastEnumeration)]) {
for(id ele in inner) {
id innerKey = [ele description];
[data setObject:[[inner valueForKey:innerKey] description] forKey:[ele description]];
}
}
else {
[data setObject:[inner description] forKey:[element description]];
}
}
NSLog([data description]);
self.weatherData = data;
}
However when check self.weatherData, I get nothing even though there is data in "data".

Issue was data isn't there when I assign it to the variable from the an asynchronous method :D
all fixed now by adding a delegate call back

Related

Convert message received from PubNub to Dictionary object

I have the following object C code for receiving PubNub message.
- (void)client:(PubNub *)client didReceiveMessage:(PNMessageResult *)message {
NSLog(#"Received message: %# on channel %# at %#", message.data.message,
message.data.subscribedChannel, message.data.timetoken);
}
The returned data is
Received message: (
{
key = userName;
value = Enoch;
},
{
key = photoID;
value = 3;
},
{
key = userID;
value = 1;
},
{
key = actionType;
value = chat;
},
{
key = message;
value = H;
}
) on channel chat at 14888810882049989
I would like to parse the message to a dictionary object for accessing the "value" by using the "key"
I am very new in objective C programming and don't know how to do.
Please help.
Loop through the message array and set the key value in dictionary.
NSArray *array = (NSArray*)message.data.message;
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
for (NSDictionary *item in array) {
[dic setObject:[item objectForKey:#"value"] forKey:[item objectForKey:#"key"]];
}
NSLog(#"%#", dic);
Or
NSArray *array = (NSArray*)message.data.message;
NSArray *values = [array valueForKey: #"value"];
NSArray *keys = [array valueForKey: #"key"];
NSDictionary *dic = [[NSDictionary alloc] initWithObjects:values forKeys:keys];
NSLog(#"%#", dic);
You can use below method for parsing your data and convert it into dictionary
ChatterBoxMessage *chatterBoxMessage = [[ChatterBoxMessage alloc] initFromDictionary: message.data.message withTimeToken: message.data.timetoken];
[chatterBoxMessage asDictionary];
By This method you will get dictionary.
Above ChatterBoxMessage is a PubNub library class.
Also you can parse your data like below :
for (NSDictionary *objectData in message.data.message) {
NSLog(#"Value : %#",objectData[#"value"]);
NSLog(#"Key : %#",objectData[#"key"]);
}

Save json object in sqlite like text and retransform to dictionary on read

I want to save a Json Object in a field (text) sqlite and then read it again with a select and retransform to NSDictionary or NSMutableArray to parse the key/values
This is how i save actually in the sqlite DB
As you see, is a song object from the iTunes api. I want to read that object and parse it.
This is how i make the select query and save it in a NSDictionary while i filling and NSMutableArary
globals.arrayMyPlaylists = [[NSMutableArray alloc] init];
// Form the query.
NSString *query = #"select * from myplaylists";
// Get the results.
NSArray *listas = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
for (int i = 0; i < listas.count; i++) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSLog(#"lista %d %# %#", i, listas[i][0], listas[i][1]);
[dictionary setObject:listas[i][0] forKey:#"id"];
[dictionary setObject:listas[i][1] forKey:#"nombre"];
NSString *query2 = [NSString stringWithFormat:#"select cancion from canciones where idplaylist = %#", listas[i][0]];
NSArray *canciones = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query2]];
[dictionary setObject:canciones forKey:#"canciones"];
[globals.arrayMyPlaylists addObject:dictionary];
dictionary = nil;
}
When i try to read it in the cellForRowAtIndexPath method
NSArray *canciones = [[NSArray alloc] initWithArray:[[globals.arrayMyPlaylists objectAtIndex:indexPath.row] valueForKey:#"canciones"]];
and try to get the value for the key artworkUrl100
[cell.tapa1 sd_setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", [[canciones objectAtIndex:i] valueForKey:#"artworkUrl100"]]] placeholderImage:nil];
i get the error
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x7ff575810600> valueForUndefinedKey:]: this class is not key value coding-compliant for the key artworkUrl100.'
i understand i'm messing up in some way with dictionarys/nsmutablearrays. I need some help. Thanks!
EDIT: this is how i save the data in the DB
NSString *query = [NSString stringWithFormat:#"insert into canciones (idplaylist, cancion) values ('%#', '%#')", [[globals.arrayMyPlaylists objectAtIndex:indexPath.row] valueForKey:#"id"], self.elementoSeleccionado];
[self.dbManager executeQuery:query];
self.elementoSeleccionado is the NSMutableArray with the "cancion" object and it's saved like it's shows the first image.
EDIT 2: this is what i get trying schmidt9's answer
EDIT 3: OK, i have the json string escaped. How i have to parse now?
You should parse your output first with NSJSONSerialization:
NSString *query2 = [NSString stringWithFormat:#"select cancion from canciones where idplaylist = %#", listas[i][0]];
NSArray *canciones = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query2]];
// I suppose your array canciones should contain only one song object ...
NSError *error = nil;
id object = [NSJSONSerialization JSONObjectWithData:canciones[0] options:0 error:&error];
if(error) {
// handle error ...
}
if([object isKindOfClass:[NSDictionary class]])
{
NSDictionary *result = object;
[dictionary setObject:result forKey:#"canciones"];
}
Edit
Saving to database
2 options:
- if you get a prepared json string, save it directly to DB, but before you should escape quotes. See eg. here
- if you have NSDictionary:
- (NSString*)JSONStringWithDictionary:(NSDictionary*)dictionary prettyPrinted:(BOOL)prettyPrinted
{
NSJSONWritingOptions options = (prettyPrinted) ? NSJSONWritingPrettyPrinted : 0;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:options error:nil];
return [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
}
After that you should escape the string too.

How assign value to a JSON string?

I get this JSON object from my web service
0: {
Username: "John"
Password: "12345"
Position: "Admin"
Job: "Developer"
ResourceJobId: 1
}
When I try to assign a value, for example, to Username JSON string, I get a semantic error:
id obj = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments
error:&error];
for (NSDictionary *dictionary in array) {
NSString *usernameString = #"";
//this line of code gives me an error: Expression is not assignable
[dictionary objectForKey:#"Username"] = usernameString ;
I know how get the JSON object with NSJSONSerialization class, but my target is how assign the value #"" to the JSON object.
So how can I assign the value #"" to the Username JSON string?
While you are trying to fetched dictionary from array. it is not mutable dictionary so you need to created NSMutableDictionary while fetching data from Array. following code will help you to change username.
for (NSMutableDictionary *dictionary in array)
{
NSMutableDictionary* dictTemp = [NSMutableDictionary dictionaryWithDictionary:dictionary];
[dictTemp setObject:usernameString forKey#"Username"];
[_arrayList replaceObjectAtIndex:index withObject:dictTemp];
}
Well your assignment operation is written wrong, it should be indeed like this:
If you need to get value from dictionary
usernameString = [dictionary objectForKey:#"Username"];
If you want to set a value to your dictionary, first of all your dictionary should be NSMutableDictionary
[dictionary setObject:usernameString forKey:#"Username"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
id obj = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments
error:&error];
if(!error && [obj isKindOfClass:[NSArray class]]){
NSArray *array = (NSArray *)obj;
Booking *booking = nil;
for (NSMutableDictionary *dictionary in array) {
NSString *usernameString = #"";
//this line of code gives me an error: Expression is not assignable
[dictionary objectForKey:#"Username"] = usernameString;
Yes, is a compiler error
You need to have a mutabledictionary inorder to change the value. Try this
for (NSDictionary *dictionary in array) {
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary];
NSString *usernameString = #"";
[mutableDictionary setValue:#"" forKey:usernameString];
}
Even the answers are correct, I want to add that you do not have to do this your own. NSJSONSerialization already has a solution for that. Simply pass as options one of these:
NSJSONReadingMutableContainers = (1UL << 0),
NSJSONReadingMutableLeaves = (1UL << 1),
when reading the JSON.

How should I read the data from a json string? iphone

I have in a NSString "[{"van" : 1,312, "vuan":12,123}] and in order to get this values for every key, I am doing this:
NSData *data1 = [jsonResponse1 dataUsingEncoding:NSUTF8StringEncoding];
jsonArray = [NSJSONSerialization JSONObjectWithData:data1 options:kNilOptions error:&err];
self.van = [NSMutableArray arrayWithCapacity:1];
self.vuan = [NSMutableArray arrayWithCapacity:1];
for (NSDictionary *json in jsonArray) {
NSString * value = [json objectForKey:#"van"];
[self.van addObject:value];
lbl1.text = value;
NSString * value1 = [json objectForKey:#"vuan"];
[self.vuan addObject:value1];
lbl4.text = value1;
}
May be I don't have to use an array and instead to convert the NSData directly in a NSDictionary.
Anyway, I don't understand why jsonArray is nil, although jsonResponse1 contains the values I have written above.
EDIT: My boss have written the json string wrong. Thank you all for your suggestions!:)
Your JSON is invalid. Fix it. This site is your friend.
http://jsonlint.com/
You need to code more defensively and you need to report errors as they are found.
Firstly check if the JSON parsing failed and if so report the error:
NSData *data1 = [jsonResponse1 dataUsingEncoding:NSUTF8StringEncoding];
jsonArray = [NSJSONSerialization JSONObjectWithData:data1 options:kNilOptions error:&err];
if (jsonArray == nil)
{
NSLog(#"Failed to parse JSON: %#", [err localizedDescription]);
return;
}
Secondly if those keys are not in the JSON, objectForKey: will return nil and when you attempt to add that to the arrays, it will throw an exception, which is something you want to avoid:
for (NSDictionary *json in jsonArray) {
NSString * value = [json objectForKey:#"van"];
if (value != nil)
{
[self.van addObject:value];
lbl1.text = value;
}
else
{
NSLog(#"No 'van' key in JSON");
}
NSString * value1 = [json objectForKey:#"vuan"];
if (value1 != nil)
{
[self.vuan addObject:value1];
lbl4.text = value1;
}
else
{
NSLog(#"No 'vuan' key in JSON");
}
}
So in summary: runtime errors will occur so you need to ensure you handle them. When they occur you need to report them with as much information possible so that you can diagnose and fix them.

NSNull value inside a object generated by JSONKit (or similar)

I'm storing the result of JSONKit parse in a key/value database (LevelDB), but the JSON I'm downloading has some filed set to null, and this won't let you serialize the corresponding generated object (NSArray or NSDictionary), to store it as an object.
¿Any idea how can I deep iterate over a NSSomething (Dictionary or Array) to change those values?
There is a post https://github.com/johnezang/JSONKit/issues/25 that explains how to modify the framework to omit it from dictionaries and array's
Sometime it happened to me that a null value was set to something what was not recognized neither as NSNull nor as NSString. Therefore i´ve replaced all null strings in the json string before i parse it with NSJSONSerialization. I´ve read the data into a NSData object, copied it into a NSString object, replaced the null strings and copied it again into a NSData object as NSJSONSerialization expects a NSData object. Maybe you can write it shorter but it works.
Here´s the code
NSString *jsonPath = [myPath stringByAppendingPathComponent:#"myDataFile.json"];
NSMutableData *myJSON = [[NSMutableData alloc] initWithContentsOfFile:jsonPath];
NSString *jsonString = [[NSString alloc] initWithBytes:myJSON.bytes length:myJSON.length encoding:NSUTF8StringEncoding];
jsonString = [jsonString stringByReplacingOccurrencesOfString:#"null" withString:#"\"placeholder\""];
NSData * jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&jsonParsingError];
after that all previous null occurances will contain a placeholder string.
I parsed the JSON to a mutableObject [[JSONDecoder decoder] mutableObjectWithUTF8String:(const unsigned char *) [json UTF8String] length:[json lengthOfBytesUsingEncoding:NSUTF8StringEncoding] error:nil ]; and then used this code to fix it:
-(id) fixObject: (id) a
{
if([a isKindOfClass:[NSMutableDictionary class]])
{
NSMutableDictionary *ad = a;
for (NSObject *key in ad)
{
if([[ad objectForKey:key] isKindOfClass:[NSMutableDictionary class]] || [[ad objectForKey:key] isKindOfClass:[NSMutableArray class]])
[self fixObject:[ad objectForKey:key]];
else
{
if((NSNull *)[ad objectForKey:key] == [NSNull null]) [ad setObject:#"" forKey:key];
}
}
}else if([a isKindOfClass:[NSMutableArray class]])
{
NSMutableArray *ar = a;
for (NSObject *ob in ar)
{
if([ob isKindOfClass:[NSMutableDictionary class]] || [ob isKindOfClass:[NSMutableArray class]])
{
[self fixObject:ob];
}
else if((NSNull *)ob == [NSNull null])
{
[ar removeObject:ob];
}
}
}
return a;
}
If you find a better way to do this, let me know!

Resources