I have an array self.seachResult which contains dictionary, I want to add an item to all dictionaries I tried a code like this but I got error, can you provide me by a code that add item 'distance' to it
[[self.seachResult objectAtIndex:0] setObject:#"distance" forKey:#"400"];
this is my array of dictionary:
2013-07-19 02:13:24.929 MyApp[59321:16a03] sorted array of dictionaries: (
{
cid = 2;
image = "http:///images/loginlogo.png";
latitude = "48.245565";
longitude = "16.342333";
manual = "";
movie = "http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v";
pcode = 023942435228;
pid = 1;
pname = "example product";
price = "12.00";
qrcode = "";
rid = 1;
rname = "Example Retailer Name";
sale = 0;
"sale_percent" = 0;
"sale_price" = "0.00";
text = "here is text about sample product number 1...\nasdasdasda\nsdfsdfsd\nSdfsdf\nSDfsdfs\ndfsdfsdf\n\n\n";
},
{
cid = 1;
image = "";
latitude = "";
longitude = "";
manual = "";
movie = "";
pcode = 1;
pid = 3;
pname = "test product";
price = "46.00";
qrcode = "";
rid = 2;
rname = "";
sale = 0;
"sale_percent" = 0;
"sale_price" = "35.00";
text = "some text here...
},
{
cid = 2;
image = "http:///testImage.png";
latitude = "48.245565";
longitude = "16.342333";
manual = "";
movie = "";
pcode = 1;
pid = 2;
pname = "sample product 2";
price = "126.00";
qrcode = "";
rid = 1;
rname = "Example Retailer Name";
sale = 1;
"sale_percent" = 20;
"sale_price" = "99.99";
text = "here is text about sample product number 2...\nblah blah blah\nasdasdasd \nASdasdas\nASdasdasd";
}
)
here is the error:
2013-07-19 02:49:54.261 MyApp[59376:16a03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
*** First throw call stack:
(0x3367012 0x2d27e7e 0x3366deb 0x332d347 0x13472 0x1d4d1c7 0x1d4d232 0x1d4d4da 0x1d648e5 0x1d649cb 0x1d64c76 0x1d64d71 0x1d6589b 0x1d65e93 0x1d65a88 0x20c1e63 0x20b3b99 0x1d4ddd2 0x12b9f 0x2d3b705 0x1c6f2c0 0x1c6f258 0x1d30021 0x1d3057f 0x1d2f6e8 0x1c9ecef 0x1c9ef02 0x1c7cd4a 0x1c6e698 0x37a7df9 0x37a7ad0 0x32dcbf5 0x32dc962 0x330dbb6 0x330cf44 0x330ce1b 0x37a67e3 0x37a6668 0x1c6bffc 0x288d 0x27b5)
libc++abi.dylib: terminate called throwing an exception
here is where I create it:
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
self.seachResult =[NSJSONSerialization JSONObjectWithData:responseData options:nil error:nil];
// [self.productsTableView reloadData];
NSMutableArray *testSorted = [self.seachResult sortedArrayUsingComparator:^NSComparisonResult(NSMutableDictionary *obj1, NSMutableDictionary *obj2) {
NSString *price1 = obj1[#"price"];
NSString *price2 = obj2[#"price"];
NSNumber *n1 = [NSNumber numberWithFloat:[price1 floatValue]];
NSNumber *n2 = [NSNumber numberWithFloat:[price2 floatValue]];
return [n1 compare:n2];
}];
[[self.seachResult objectAtIndex:0] setObject:#"distance" forKey:#"400"];
NSLog(#"sorted array of dictionaries: %#", testSorted);
Your objects created from JSON are all immutable.
self.seachResult =[NSJSONSerialization JSONObjectWithData:responseData options:nil error:nil];
instead of passing nil for options pass NSJSONReadingMutableContainers:
self.seachResult =[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil];
From the NSJSONSerialization docs:
NSJSONReadingMutableContainers
Specifies that arrays and dictionaries are created as mutable objects.
Related
I am trying to parse JSON, using Objective-C This is the NSLog Echoed with my current code.
{
KnowledgeBaseEntry = {
AllowBotAccess = 1;
FulltextSearch = 1;
GroupId = "";
Id = 611552aea1fe4d789e31133d3ee77f35;
IsPublic = 1;
Languages = "";
OwnerId = 8c427d5;
ParentId = 1;
ShortcutWord = "";
Tags = "";
Title = "Another Test Cell";
Type = 1;
Value = "This <BR>Is<BR>testing";
};
},
{
KnowledgeBaseEntry = {
AllowBotAccess = 1;
FulltextSearch = 1;
GroupId = "";
Id = fc4f1a90243246bb93641b0c8db689b9;
IsPublic = 1;
Languages = "";
OwnerId = 8c427d5;
ParentId = 1;
ShortcutWord = "";
Tags = "";
Title = "Cydo Error 2";
Type = 1;
Value = "content<BR><BR>this is contenty";
};
},
{
KnowledgeBaseEntry = {
AllowBotAccess = 1;
FulltextSearch = 1;
GroupId = "";
Id = bd057d5443194d7a98c2398e07de919e;
IsPublic = 1;
Languages = "";
OwnerId = 8c427d5;
ParentId = 1;
ShortcutWord = "";
Tags = "";
Title = testkb2;
Type = 1;
Value = "test content!";
};
}
)
I need to use the Title to grab what is in the Value so I can display in app. I can access the Title Var but I have no idea how to match the two to NSLog the Value. Any help is appreciated.
Here is the current code:
NSData *rGeniusData = [[NSData alloc] initWithContentsOfURL:
[NSURL URLWithString:#"http://jbbar.ml/rgenius/ipapi.php"]];
//Parse The JSON
NSError *error;
NSMutableDictionary *allKB = [NSJSONSerialization JSONObjectWithData:rGeniusData
options:NSJSONReadingMutableContainers
error:&error];
NSArray *kb = allKB[#"KnowledgeBaseEntries"];NSLog(#"AboveDP= %#", kb);
Parse like this
NSDictionary *dict;
NSString *strAllowBotAccess =[[dict objectForKey:#"KnowledgeBaseEntry"]objectForKey:#"AllowBotAccess"];
NSLog(#"dict=====%#", strAllowBotAccess);
Try https://github.com/jsonmodel/jsonmodel
JSONModel allows rapid creation of smart data models. You can use it in your iOS, macOS, watchOS and tvOS apps. Automatic introspection of your model classes and JSON input drastically reduces the amount of code you have to write.
Easy to use, you can parse all keys or some of them.
#interface YourModel : JSONModel
#property (nonatomic) NSInteger id;
#property (nonatomic) NSString *value;
#end
#implementation YourModel
+ (JSONKeyMapper *)keyMapper
{
return [[JSONKeyMapper alloc] initWithModelToJSONDictionary:#{
#"id": #"Id",
#"value": #"KnowledgeBaseEntry.Value"
}];
}
#end
Apologies if this is a novice question, but I've been struggling to figure this out with no luck. I'm trying to pull a users' twitter timeline using the AFOAuth2Manager framework. Everything makes sense except the returned JSON object is an array and the entire object is one giant object. I obviously want to break it up into different elements and store them in a dictionary, but have not been able to figure it out so far.
This is a VERY partial example of what the array object looks like. The complete object is this with about 20 or so more tweets with this format attached. I will post the entire json object if requested, but it seems pretty pointless to post the entire thing.
Heres my code:
[manager GET:#"/1.1/statuses/user_timeline.json?screen_name=jack"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject ) {
self.object = responseObject;
NSLog(#"Success: %#", responseObject);
if ([responseObject isKindOfClass:[NSArray class]]) {
NSLog(#"object is a nsarray class");
} else if ([responseObject isKindOfClass:[NSDictionary class]]){
NSLog(#"object is a nsdictionary class");
} else {
NSLog(#"object is a different class");
}
NSArray *response = [NSArray arrayWithObject:responseObject];
NSLog(#"count %ld", [response count]);
NSData *dataFromTwitter = [NSKeyedArchiver archivedDataWithRootObject:self.object];
NSError *parseError = nil;
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:dataFromTwitter
options:NSJSONReadingMutableLeaves | NSJSONReadingMutableContainers|NSJSONReadingAllowFragments
error:&parseError];
NSLog(#"response Dict: %#", responseDict);
NSError *e = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:dataFromTwitter
options:NSJSONReadingAllowFragments
error:&e];
NSLog(#"jsonArray: %#", jsonArray);
NSError *jsonError2 = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:dataFromTwitter
options:NSJSONReadingAllowFragments
error:&jsonError2];
if ([jsonObject isKindOfClass:[NSArray class]]) {
NSLog(#"its an array!");
NSArray *jsonArray = (NSArray *)jsonObject;
NSLog(#"jsonArray2 - %#",jsonArray);
}
else {
NSLog(#"its probably a dictionary");
NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
NSLog(#"jsonDictionary - %#",jsonDictionary);
NSLog(#"error %#", jsonError2);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", error);
}];
{
contributors = "<null>";
coordinates = "<null>";
"created_at" = "Mon Feb 29 01:18:05 +0000 2016";
entities = {
hashtags = (
);
symbols = (
);
urls = (
);
"user_mentions" = (
{
id = 14616957;
"id_str" = 14616957;
indices = (
0,
7
);
name = "Jason Del Rey";
"screen_name" = DelRey;
},
{
id = 19040598;
"id_str" = 19040598;
indices = (
8,
18
);
name = "\U0ca0_\U0ca0";
"screen_name" = MikeIsaac;
},
{
id = 46063;
"id_str" = 46063;
indices = (
19,
30
);
name = "Hunter Walk";
"screen_name" = hunterwalk;
}
);
};
"favorite_count" = 12;
favorited = 0;
geo = "<null>";
id = 704113377920978944;
"id_str" = 704113377920978944;
"in_reply_to_screen_name" = DelRey;
"in_reply_to_status_id" = 704112911116013568;
"in_reply_to_status_id_str" = 704112911116013568;
"in_reply_to_user_id" = 14616957;
"in_reply_to_user_id_str" = 14616957;
"is_quote_status" = 0;
lang = en;
place = "<null>";
"retweet_count" = 0;
retweeted = 0;
source = "Twitter for iPhone";
text = "#DelRey #MikeIsaac #hunterwalk this changes everything";
truncated = 0;
user = {
"contributors_enabled" = 0;
"created_at" = "Tue Mar 21 20:50:14 +0000 2006";
"default_profile" = 0;
"default_profile_image" = 0;
description = "#withMalala!";
entities = {
description = {
urls = (
);
};
};
"favourites_count" = 11433;
"follow_request_sent" = "<null>";
"followers_count" = 3458722;
following = "<null>";
"friends_count" = 1859;
"geo_enabled" = 1;
"has_extended_profile" = 1;
id = 12;
"id_str" = 12;
"is_translation_enabled" = 0;
"is_translator" = 0;
lang = en;
"listed_count" = 25944;
location = "California, USA";
name = Jack;
notifications = "<null>";
"profile_background_color" = EBEBEB;
"profile_background_image_url" = "http://abs.twimg.com/images/themes/theme7/bg.gif";
"profile_background_image_url_https" = "https://abs.twimg.com/images/themes/theme7/bg.gif";
"profile_background_tile" = 0;
"profile_image_url" = "http://pbs.twimg.com/profile_images/668328458519384064/FSAIjKRl_normal.jpg";
"profile_image_url_https" = "https://pbs.twimg.com/profile_images/668328458519384064/FSAIjKRl_normal.jpg";
"profile_link_color" = 990000;
"profile_sidebar_border_color" = DFDFDF;
"profile_sidebar_fill_color" = F3F3F3;
"profile_text_color" = 333333;
"profile_use_background_image" = 1;
protected = 0;
"screen_name" = jack;
"statuses_count" = 19066;
"time_zone" = "Pacific Time (US & Canada)";
url = "<null>";
"utc_offset" = "-28800";
verified = 1;
};
},
You show no code in your question, in a comment you state you have a responseObject but not how you came by it.
The JSON you are getting from somewhere will be text, you may have it as an NSString, NSData, an NSArray whose elements are these, etc.
You need to obtain that text and then parse it as JSON, the NSJSONSerialization class will handle the parsing for you, the first line of its description states:
You use the NSJSONSerialization class to convert JSON to Foundation objects and convert Foundation objects to JSON.
Once you have those Foundation objects - arrays, dictionaries, strings, numbers, etc. you can extract the fields you are interested in.
Once you've written some code to do this if it doesn't work and you are stuck ask a new question showing your code and someone will probably be able to help you further.
HTH
I have an array(seachResult) which contains dictionaries and I want to sort this array according to 'price' key in the dictionary that is a number in string format.
I tried this code but it doesn't work for sorting 'price' but it works for pid which is a number.
how can I sort it according 'price' (number in string format)?
NSSortDescriptor *sortByPrice = [NSSortDescriptor sortDescriptorWithKey:#"price" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByPrice];
NSArray *sortedArray = [self.seachResult sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"%#",sortedArray );
here is sample data for self.searchResult:
2013-07-17 02:04:55.012 MyApp[57014:16a03] sorted array of dictionaries: (
{
cid = 2;
image = "http:///images/loginlogo.png";
latitude = "48.245565";
longitude = "16.342333";
manual = "";
movie = "http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v";
pcode = 023942435228;
pid = 1;
pname = "example product";
price = "12.00";
qrcode = "";
rid = 1;
rname = "Example Retailer Name";
sale = 0;
"sale_percent" = 0;
"sale_price" = "0.00";
text = "here is text about sample product number 1...\nasdasdasda\nsdfsdfsd\nSdfsdf\nSDfsdfs\ndfsdfsdf\n\n\n";
},
{
cid = 2;
image = "http:///testImage.png";
latitude = "48.245565";
longitude = "16.342333";
manual = "";
movie = "";
pcode = 1;
pid = 2;
pname = "sample product 2";
price = "126.00";
qrcode = "";
rid = 1;
rname = "Example Retailer Name";
sale = 1;
"sale_percent" = 20;
"sale_price" = "99.99";
text = "here is text about sample product number 2...\nblah blah blah\nasdasdasd\nASdasdas\nASdasdasd";
},
{
cid = 1;
image = "";
latitude = "";
longitude = "";
manual = "";
movie = "";
pcode = 1;
pid = 3;
pname = "test product";
price = "46.00";
qrcode = "";
rid = 2;
rname = "";
sale = 0;
"sale_percent" = 0;
"sale_price" = "35.00";
text = "some text here...
\nasdasd
\nasd
\na
\nsd
\nas
\nd";
}
)
I also tried this code :
NSSortDescriptor *hopProfileDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"price"
ascending:YES];
NSArray *descriptors = [NSArray arrayWithObjects:hopProfileDescriptor, nil];
NSArray *sortedArrayOfDictionaries = [self.seachResult
sortedArrayUsingDescriptors:descriptors];
NSLog(#"sorted array of dictionaries: %#", sortedArrayOfDictionaries);
but still doesn't work.
I think the issue is that in your self.searchResult array the price data is differently formatted for the objects in the array.
The first object in the array it's formatted like price = 12; (probably a NSDecimalNumber)
The second object in the array it's formatted like price = "125.99"; (proably a NSString)
NSArray *testSorted = [test sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
NSString *price1 = obj1[#"price"];
NSString *price2 = obj2[#"price"];
NSNumber *n1 = [NSNumber numberWithFloat:[price1 floatValue]];
NSNumber *n2 = [NSNumber numberWithFloat:[price2 floatValue]];
return [n1 compare:n2];
}];
Since your price data seems to vary (NSString vs NSNumber) you might try instead using sortedArrayUsingComparator:. eg:
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
id value1 = [obj1 objectForKey:#"price"];
float float1 = [value1 floatValue];
id value2 = [obj2 objectForKey:#"price"];
float float2 = [value2 floatValue];
if (float1 < float2) {
return NSOrderedAscending;
}
else if (float1 > float2) {
return NSOrderedDescending;
}
return NSOrderedSame;
}];
This is kinda ugly but should get you started. It's also fragile--if you get something other than NSNumber or NSString for the price it'll likely crash.
Imagine I make an request to my api that return an mysql_query("Select * from user where id=1").
After the request is done, it returns the user info in json.
I do some debuging, NSlog(#"JSON : %#",json); and it gives me this:
JSON : (
{
aboutme = "";
active = 0;
birthday = "1992-10-14";
"city_id" = 0;
email = "test#test.com";
fbid = "";
firstname = test;
gender = 1;
id = 162;
lastname = test;
password = "$2a$12$8iy.sGr.4V/Ea3GfHZe0m.SLDrvoSj3/wYRlWsNce1yyCMeCbDrMC";
"phone_number" = "";
"recovery_date" = "0000-00-00 00:00:00";
"register_date" = "2013-06-06 02:44:20";
salt = "8iy.sGr.4V/Ea3GfHZe0m";
"user_type_id" = 1;
username = test;
}
)
Now I parse it with AFJONDecode and when I get the [json valueForKey:#"username"]; and debug it ( NSlog(#"username = %#",[json valueForKey#"username"]); ) and I get this:
username = (
testeteste739
)
It gives me an object ( because in the Json, the username = test and not username = "test").
So, how can i convert this object to string?
** UPDATE **
I resolve it by the following way:
NSArray *username = [JSON valueForKey:#"username"];
username = [username objectAtIndex:0];
Is there any better way to overpass this?
Thanks
As JSON is a dictionary object, so you can get your json data to JSONDic NSDictionary variable and parse it to string as follows:-
NSDictionary *JSONDic=[[NSDictionary alloc] init];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:JSONDic
options:NSJSONWritingPrettyPrinted
error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
So I have a NSMutableArray of objects I need to save to a file. Saving it with writeToFile method will not work because I have NSNull values which are not allowed in the .plist format that this method generates.
So I am saving my file to disk by saving it as a NSString:
NSString *content = [NSString stringWithFormat:#"%#",orders];
[content writeToFile:ordersFilePath atomically:NO];
Which generates a file like this:
(
{
ZBILLINGADDRESS1 = "";
ZBILLINGADDRESS2 = "";
ZBILLINGCITY = "";
ZBILLINGCOUNTRY = "";
ZBILLINGSTATE = "";
ZBILLINGZIP = "";
ZCANCELDATE = "<null>";
ZCATALOGCODE = "";
ZCATALOGNAME = "";
ZCONTACTEMAIL = "";
ZCONTACTFAX = "";
ZCONTACTNAME = " ";
ZCONTACTPHONE = "";
ZCONTAINERCUBES = 0;
ZCONTAINERNAME = "";
ZCURRENCYCODE = "<null>";
ZCUSTOMERID = 0;
ZCUSTOMERNAME = "Dupe offline Test";
ZCUSTOMERNUMBER = 1297145;
ZDISCOUNT = 0;
ZDONOTSHIPBEFORE = "<null>";
ZEXPORTDATE = "-63113886238";
ZEXPORTED = 1;
ZFOB = "";
ZFREIGHTTERM = "";
ZISCONTAINER = 0;
ZISDEFAULT = 0;
ZISDELETED = 0;
ZISPLACED = 0;
ZMANUFACTURERID = 18;
ZMARKETNAME = "";
ZNOTES = "last second note";
ZORDERDATE = 372571200;
ZORDERGUID = "5650d30a-9316-436a-87e9-1e0ead3af8d7";
ZORDERID = 84340;
ZORDERSTATUS = Accept;
ZORDERTOTAL = 200;
ZORDERTYPE = "";
ZORIGIN = "";
ZPONUMBER = 3;
ZPRICELEVEL = 2;
ZREPNUMBER = 1;
ZSALESREPID = 235;
ZSHIPDATE = 373176000;
ZSHIPPINGTOTAL = 0;
ZSHIPTOADDRESS1 = "";
ZSHIPTOADDRESS2 = "";
ZSHIPTOCITY = "";
ZSHIPTOCOMPANYNAME = "";
ZSHIPTOCONTACTEMAIL = "";
ZSHIPTOCONTACTNAME = "";
ZSHIPTOCONTACTPHONE = "";
ZSHIPTOCOUNTRY = "";
ZSHIPTOFAX = "";
ZSHIPTOSTATE = "";
ZSHIPTOZIP = "";
ZSHIPVIA = "";
ZSOURCE = ipad;
ZSUBTOTAL = 200;
ZTAXRATE = 0;
ZTAXTOTAL = 0;
ZTERMS = "";
ZWRITTENBYNAME = "";
ZWRITTENFORNAME = "";
ZWRITTENFORREPNUMBER = "";
ZWRITTENFORREPNUMBER1 = "<null>";
"Z_ENT" = 17;
"Z_OPT" = 5;
"Z_PK" = 450;
}
)
problem is when I try and reload this as an NSArray I get a null value:
NSString *str = [NSString stringWithContentsOfFile:ordersFilePath encoding:NSUTF8StringEncoding error:NULL];
NSArray *loadedOrders = [[NSArray alloc] initWithContentsOfFile:str];
What am I missing here?
NSArray *loadedOrders = [[NSArray alloc] initWithContentsOfFile:str];
initWithContentsOfFile takes path as string. In your case it is not path but content itself.
What I see is that your string is actually a description of CoreData's NSManagedObject (orders array). So you can save your string to a file, but you can't recreate the same object from this file. This is just the result of the -description method on your NSManagedObject. You must implement custom logic of saving your object's data (else where, not your CoreData's persistent store, and a logic that will load that data, by inserting it in a NSManagedObjectContext) if that's what you are trying to achieve.
[NSString stringWithFormat:#"%#",orders] just gives you the result of calling [orders description] which is just for debugging not for archiving it.
You could just call writeToFile:atomically: on your orders array and then do [[NSArray alloc] initWithContentsOfFile:filePath] to read it back out, there is one caveat:
If the array’s contents are all property list objects (NSString, NSData, NSArray, or NSDictionary objects), the file written by this method can be used to initialize a new array with the class method arrayWithContentsOfFile: or the instance method initWithContentsOfFile:. This method recursively validates that all the contained objects are property list objects before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.
so the objects in the array must all be NSString, NSData, NSArray, or NSDictionary classes in order for this to work.