My response is like;
{
Writers : [
{
"name": "Mad Decent Block Party NYC",
"artist": [
{
"artist_name": "Dillon Francis",
"name": "Dillon Francis",
"Books" : ["Book1", "Book2", "Book3"]
},
{
"artist_name": "Major Lazer",
"name": "Major Lazer",
"Books" : ["Book4", "Book5", "Book6"]
},
{
"artist_name": "Flosstradamus ",
"name": "Flosstradamus",
"Books" : ["Book7", "Book8", "Book9"]
}
],
},{
"name": "Kaskade Atmosphere Tour NYC",
"artist": [
{
"artist_name": "Ryan Raddon",
"name": "Kaskade",
"Books" : ["Book1", "Book2", "Book3"]
}
],
},
]
}
I want to search through Books array on each dict of artist array. When text matches result should be total dict object from writers array along with matched books objects.
For example my search is for Book1, result should look like,
Writers : [
{
"artist": [
{
"artist_name": "Dillon Francis",
"name": "Dillon Francis",
"Books" : ["Book1", "Book2", "Book3"]
},
],
"name": "Mad Decent Block Party NYC",
},{
"artist": [
{
"artist_name": "Ryan Raddon",
"name": "Kaskade",
"Books" : ["Book1", "Book2", "Book3"]
}
],
"name": "Kaskade Atmosphere Tour NYC",
},
]
You just need to write two lines of code for this. You form a predicate, and filter the writers array with the predicate.
You can use the keypaths in the predicate, and check if the book array contains the given book name.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY artist.Books contains[cd] 'Book1'"];
NSArray *arr = [responseDict[#"Writers"] filteredArrayUsingPredicate:predicate];
This should work.
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"ANY artist.Books CONTAINS[cd] %#", #"Book1"];
NSArray *temp = [[sampleDic objectForKey:#"Writers"] filteredArrayUsingPredicate:predicate];
This is the first thing i thought, but looking at your dictionary structure, i think this will not work for you. But if you want to recreate your structure to:
#{
#"Writers":
#[
#{
#"name" :#"name1",
#"artist" :#[ #"Books":[...] ]
},
#{
#"name" :#"name2",
#"artist" :#[ #"Books":[...] ]
},
#{
#"name" :#"name3",
#"artist" :#[ #"Books":[...] ]
}
]
};
it will.
This is not the best solution but i think this will work for you..
Sample input:
NSDictionary *sampleDic = #{
#"Writers":
#[
#{
#"name" :#"Mad Decent Block Party NYC",
#"artist" :#[
#{
#"artist_name":#"Dillon Francis",
#"name": #"Dillon Francis",
#"Books" : #[#"Book1", #"Book2", #"Book3"]
},
#{
#"artist_name":#"Major Lazer",
#"name": #"Major Lazer",
#"Books" : #[#"Book4", #"Book5", #"Book6"]
},
#{
#"artist_name":#"Flosstradamus",
#"name": #"Flosstradamus",
#"Books" : #[#"Book7", #"Book8", #"Book9"]
}
]
},
#{
#"name" :#"Kaskade Atmosphere Tour NYC",
#"artist" :#[
#{
#"artist_name":#"Ryan Raddon",
#"name": #"Kaskade",
#"Books" : #[#"Book1", #"Book2", #"Book3"]
}
]
}
]
};
And the filtering:
- (NSDictionary *)filterDictionary:(NSDictionary *)sampleDic withBookName:(NSString *)bookName
{
NSMutableArray *compiledArr = [[NSMutableArray alloc] init];
for (NSDictionary *itemDic in [sampleDic objectForKey:#"Writers"])
{
NSArray *itemDicKeys = [itemDic allKeys];
for (int i = 0; i < itemDicKeys.count; i++)
{
if ([itemDicKeys[i] isEqual:#"artist"])
{
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"SELF['Books'] CONTAINS[cd] %#", bookName];
NSArray *tempResult = [[itemDic objectForKey:itemDicKeys[i]] filteredArrayUsingPredicate:predicate];
NSDictionary *result = #{#"name": [itemDic objectForKey:#"name"],
#"artist": tempResult};
[compiledArr addObject:result];
}
}
}
NSDictionary *resultDic = #{#"Writer":compiledArr};
return resultDic;
}
Using it like: NSLog(#"tempResult :%#", [self filterDictionary:sampleDic withBookName:#"Book1"]);
Result is:
Related
Here's the response:
{
"status": true,
"statuscode": 200,
"result": [
{
"name": "ABC",
"date": "2015-01-30",
"documents": [
{
"id": 1,
"name": "doc1",
"status": "complete",
},
{
"id": 2,
"name": "doc2",
"status": "complete",
},
{
"id": 3,
"name": "doc3",
"status": "complete",
}
],
"message": "Hello World",
"status": 3
}
]
}
I want to map and get only all the "document" inside an array keyed "result" and I don't need anything with other objects / mappings. I just need the documents. How can that be done / declared in the response descriptors to automatically match all these documents to my managed object?
Try This :-
NSDictionary *dic=#{
#"status": #true,
#"statuscode":# 200,
#"result": #[
#{
#"name": #"ABC",
#"date": #"2015-01-30",
#"documents": #[
#{
#"id":# 1,
#"name": #"doc1",
#"status": #"complete",
},
#{
#"id":# 2,
#"name": #"doc2",
#"status":# "complete",
},
#{
#"id":# 3,
#"name": #"doc3",
#"status": #"complete",
}
],
#"message": #"Hello World",
#"status":# 3
}
]
};
I am storing your response in NSDictionary and get it by -
[[[dic objectForKey:#"result"] objectAtIndex:0] objectForKey:#"documents"]
change your indexNumber as require !
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error]; //From Server you will get response data in form of NSData , so the 'responseData' is a type of NSData
NSArray *appDetais = [jsonData objectForKey:#"result"];
NSDictionary *resultJsonData = [appDetais objectAtIndex:0];
NSArray *documentDetailsArray = [jsonData resultJsonData:#"documents"];
for(int i=0;i<[documentDetailsArray count];i++){
NSDictionary *singleDocumentDetail = [documentDetailsArray objectAtIndex:0];
NSLog(#"%#",[singleDocumentDetail objectForKey:#"id"]);
}
You may try this.. :)
Array format:
{
"sku": "NikeL101Black",
"name": "Nike Black shirt -L",
"attribute_set_id": 4,
"price": 30,
"status": 1,
"visibility": 1,
"type_id": "simple",
"created_at": "2015-12-01 23:02:07",
"updated_at": "2015-12-01 23:02:23",
"weight": 2,
"product_links": [],
"options": [],
"tier_prices": [],
"custom_attributes": [
{
"attribute_code": "swatch_image",
"value": "/m/i/miler-uv-mens-t-shirt-black-p7394-6131_zoom_1_1.jpg"
},
{
"attribute_code": "tax_class_id",
"value": "2"
},
{
"attribute_code": "image",
"value": "/m/i/miler-uv-mens-t-shirt-black-p7394-6131_zoom_1_1.jpg"
},
{
"attribute_code": "category_ids",
"value": [
"3"
]
},
{
"attribute_code": "description",
"value": "<p>Cool black nike tshirt</p>"
},
{
"attribute_code": "color",
"value": "7"
},
{
"attribute_code": "required_options",
"value": "0"
},
{
"attribute_code": "size",
"value": "14"
},
{
"attribute_code": "has_options",
"value": "0"
},
{
"attribute_code": "vendor",
"value": "Paxcel Cloth House"
},
{
"attribute_code": "small_image",
"value": "/m/i/miler-uv-mens-t-shirt-black-p7394-6131_zoom_1_1.jpg"
},
{
"attribute_code": "thumbnail",
"value": "/m/i/miler-uv-mens-t-shirt-black-p7394-6131_zoom_1_1.jpg"
},
{
"attribute_code": "url_key",
"value": "nike-red-shirt-s-7"
},
{
"attribute_code": "meta_title",
"value": "Nike Red shirt -S"
},
{
"attribute_code": "meta_keyword",
"value": "Nike Red shirt -S"
},
{
"attribute_code": "meta_description",
"value": "Nike Red shirt -S <p>Cool red noke tshirt</p>"
},
{
"attribute_code": "options_container",
"value": "container2"
}
]
},
How to filter an array of above type dictionaries by (attribute_code = color and value = 7) AND (attribute_code = size and value = 12)
I tried with a compound predicate:
NSPredicate *filterChildrenBySize = [NSPredicate predicateWithFormat:#"ANY custom_attributes.attribute_code == size AND custom_attributes.value.integerValue == %#", [[attributes objectForKey:#"sizeInfo"] objectForKey:kAttributeCodeSize]];
Predicate looks like this --> ANY custom_attributes.attribute_code == color AND custom_attributes.value.integerValue == 4
You have to do like this. Check the NSLog of filterArray.
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil];
NSLog(#"OUTPUT DATA: %#" ,jsonDict);
NSArray *arrayList = [jsonDict objectForKey:#"custom_attributes"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.attribute_code == 'color' AND self.value == '7'"];
NSArray *filterArray = [arrayList filteredArrayUsingPredicate:predicate];
NSLog(#"FILTERED DATA: %#" ,filterArray);
Here 'jsonString' is the String what you provided. I just did the NSJSONSerialization to convert the Stirng into NSDictionary.
You have to merge both filters with OR instead of AND. It will never compare with AND in your case and will return 0 objects as filteredArray
Here is a compound predicate for your custom_attributes array.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(attribute_code ==[c] 'color' AND value == '7') OR (attribute_code ==[c] 'size' AND value == '12')"];
// Assuming that you have parsed you custom_attributes object to customAtrributes
NSArray *filteredArray = [customAtrributes filteredArrayUsingPredicate:predicate];
Try to use ANY for that.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"custom_attributes.value == %d", 7];
NSArray *filterArray = [yourArray filteredArrayUsingPredicate:predicate];
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"custom_attributes.attribute_code CONTAINS[c] %#", "color"];
NSArray *filterArray1 = [filterArray filteredArrayUsingPredicate:predicate1];
So I have an NSDictionary that has a variety of data within it. When printed to the log, it prints like this:
[{"user_id":3016817,"grade":"A","percent":"93","grading_periods":[{"assignments":[{"points":100.0,"grade":"A","score":95.0,"percent":"93","comment":null,"id":3268180},{"points":100.0,"grade":"A","score":90.0,"percent":"93","comment":null,"id":3268181}],"grade":"A","percent":"93","name":"Default"}]},{"user_id":3016818,"grade":"A","percent":"94","grading_periods":[{"assignments":[{"points":100.0,"grade":"A","score":92.0,"percent":"94","comment":null,"id":3268180},{"points":100.0,"grade":"A","score":95.0,"percent":"94","comment":null,"id":3268181}],"grade":"A","percent":"94","name":"Default"}]}]
If I use a formatter online, its a lot more readable and looks something like this:
[
{
"user_id": 3016817,
"grade": "A",
"percent": "93",
"grading_periods": [
{
"assignments": [
{
"points": 100,
"grade": "A",
"score": 95,
"percent": "93",
"comment": null,
"id": 3268180
},
{
"points": 100,
"grade": "A",
"score": 90,
"percent": "93",
"comment": null,
"id": 3268181
}
],
"grade": "A",
"percent": "93",
"name": "Default"
}
]
},
{
"user_id": 3016818,
"grade": "A",
"percent": "94",
"grading_periods": [
{
"assignments": [
{
"points": 100,
"grade": "A",
"score": 92,
"percent": "94",
"comment": null,
"id": 3268180
},
{
"points": 100,
"grade": "A",
"score": 95,
"percent": "94",
"comment": null,
"id": 3268181
}
],
"grade": "A",
"percent": "94",
"name": "Default"
}
]
}
]
My question would be how would I access the value of grade or score for a specific user_id using this dictionary?
Your string represents a NSArray, not a NSDictionary. And it's a JSON string, so you can parse it using NSJSONSerialization:
NSString *jsonString = #"..." // your string here
// Create array from json string
NSArray *jsonArray = [NSJSONSerialization
JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error:Nil];
// Loop to find your user_id
// Because each child of this array is a dictionary
for (NSDictionary *dic in jsonArray) {
if ([dic[#"user_id"] isEqual:#3016817]) { // user_id field is number
// Access what you want
NSString *grade = dic[#"grade"];
// For "score" you must go deeper
// Just remember, [] is array and {} is dictionary
}
}
A simple way to do this would be
for (NSDictionary* d in theArray) {
if ([d[#"user_id"] isEqualToString: u]) {
// do something
}
}
And matt is right, it is an array of dictionaries, no matter what type you declared to be.
You can use below class method of NSJsonSerialization class to create NSArray which will contain all the dictionaries.
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
Once you get the array of dictionaries from JSON, you can do following:
NSArray *filteredjsonArr = [jsonArr filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"user_id == %#", #"3016818"]];
NSDictionary *dict = [filtered firstObject];
if (dict != nil) {
NSString *grade = [dict objectForKey:#"grade"];
NSArray *gradingPeriods = [dict objectForKey:#"grading_periods"];
}
To access score and grade for specific assignments, you'll need to drill down further into gradingPeriods array.
I have following JSON response which has been stored in NSMutableDictonary. I want to addition of all the price of special_item.
{
"order_id": "1",
"order_name": "xyz",
"order_item": [
{
"item_id": "1",
"item_name": "myone",
"special_item": [
{
"s_item_id": "1",
"price": "10"
},
{
"s_item_id": "2",
"price": "100"
}
]
},
{
"item_id": "2",
"item_name": "mytwo",
"special_item": [
{
"s_item_id": "11",
"price": "15"
},
{
"s_item_id": "22",
"price": "110"
}
]
}
]
}
Is it possible to do addition of all the price using NSPredicate ? or How can I get array of all the price values using NSPredicate?(e.g : [#10,#100,#15,#110])
Thank you!
It is so simple
you can try below code
NSArray *arr = [dix valueForKeyPath:#"order_item.special_item.price"];
long total = 0;
for (id price in arr) {
if ([price isKindOfClass:[NSArray class]]) {
total += [[price valueForKeyPath:#"#sum.self"] longValue];
}
else {
total += [price longValue];
}
}
NSInteger *total=0;
NSArray *arr=[NSDictionary objectForKey=#"order_item"];
for(NSDictionary *dic in arr){
NSArray *array=[dic objectForKey=#"special_item"];
for(NSDictionary *d in array){
total=total+[[d objectForKey=#"price"] intValue];
}
}
NSLog("Total:- %d",total);
I am having a problem with one-to-many relationships in my CoreData-backed entities.
My JSON looks like this:
[
{
"uuid": "0",
"title": "humor",
"providers": [{
"provider": {
"uuid": "1",
"title": "dilbert",
"sections": [{
"section": { "uuid":"1990", "title": "daily"},
"section": { "uuid":"1991", "title": "weekly"},
}],
},
"provider": {
"uuid": "2",
"title": "wizard of id",
},
"provider": {
"uuid": "3",
"title": "bc",
},
},],
},
{
"uuid": "22",
"title": "photo",
},
]
In my case, the top level object is a category, which can have 0..* providers, which can have 0..* sections.
Update: Just to wrap this up, the root of this problem is that the JSON is malformed. There should not be trailing commas in the dictionaries.
My RestKit mappings are:
RKEntityMapping *sectionMapping = [RKEntityMapping mappingForEntityForName:#"DHSection" inManagedObjectStore:managedObjectStore];
[sectionMapping addAttributeMappingsFromDictionary:#{
#"section.uuid" : #"uuid",
#"section.title" : #"title",
}];
sectionMapping.identificationAttributes = #[#"uuid"];
RKEntityMapping *providerMapping = [RKEntityMapping mappingForEntityForName:#"DHProvider" inManagedObjectStore:managedObjectStore];
[providerMapping addAttributeMappingsFromDictionary:#{
#"provider.uuid" : #"uuid",
#"provider.title" : #"title",
}];
providerMapping.identificationAttributes = #[#"uuid"];
RKRelationshipMapping *sectionRelationship = [RKRelationshipMapping relationshipMappingFromKeyPath:#"provider.sections" toKeyPath:#"sections" withMapping:sectionMapping];
[sectionRelationship setAssignmentPolicy:RKUnionAssignmentPolicy];
[providerMapping addPropertyMapping:sectionRelationship];
RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:#"DHCategory" inManagedObjectStore:managedObjectStore];
[categoryMapping addAttributeMappingsFromDictionary:#{
#"uuid" : #"uuid",
#"title" : #"title",
}];
categoryMapping.identificationAttributes = #[#"uuid"];
RKRelationshipMapping *providerRelationship = [RKRelationshipMapping relationshipMappingFromKeyPath:#"providers" toKeyPath:#"providers" withMapping:providerMapping];
[providerRelationship setAssignmentPolicy:RKUnionAssignmentPolicy];
[categoryMapping addPropertyMapping:providerRelationship];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:categoryMapping method:RKRequestMethodGET pathPattern:#"category/list.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:#"category/list.json"];
NSDictionary *argsDict = nil;
BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
if (match) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"DHCategory"];
fetchRequest.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"uuid" ascending:YES]];
return fetchRequest;
}
return nil;
}];
When RestKit parses the response, it correctly parses two categories, but it only loads the first provider and section.
Update 1 Nov 2013: The updated mapping above corrected the relationship mapping for sections to map from key path "provider.sections" vs "sections".
The problem may likely stem from the difference between the response and what is being mapped.
2013-11-01 10:40:06.670 xyz[58006:1003] D restkit.object_mapping:RKMapperOperation.m:377 Executing mapping operation for representation: (
{
providers = (
{
provider = {
sections = (
{
section = {
title = daily;
uuid = 1990;
};
}
);
title = dilbert;
uuid = 1;
};
}
);
title = humor;
uuid = 0;
},
...
while the response was
response.body=[
{
"uuid": "0",
"title": "humor",
"providers": [
{
"provider": {
"uuid": "1",
"title": "dilbert",
"sections": [{
"section": { "uuid":"1990", "title": "daily"},
"section": { "uuid":"1991", "title": "weekly"},
}
],
},
"provider": {
"uuid": "3",
"title": "wizard of id",
},
"provider": {
"uuid": "2",
"title": "bc",
},
},
],
},
...
Any ideas on how to fix or debug this?
Thanks,
Mike