I use JSONModel to hold my app datasource, and use -(id)initWithArray:(NSArray *)array modelClass:(Class)cls generated an JSONModelArray, now I want to do some search stuff like enumerateObjectsUsingBlock: method does. But I found that JSONModelArray is not inherited from NSArray.
So, how can I do this?
Try use BWJSONMatcher to convert json string to a NSArray.
For example, your json string seems like :
[{"name":"Arron","age":20,"grade":2},{"name":"Burrows","age":21,"grade":2}]
All you have to do is declare your own data model:
#interface Student : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, assign) NSInteger age;
#property (nonatomic, assign) NSInteger grade;
#end
BWJSONMatcher will help you convert it to a NSArray in a very neat way:
NSArray *students = [BWJSONMatcher matchJSON:jsonString withClass:[Student class]];
Related
I know my question is a little confusing so please allow me to elaborate.
JSON Parsing Lib : JSONModelLib
MODEL
#import "JsonModelLib/JSONModel.h"
#interface CustomerDetailsModel : JSONModel
#property (nonatomic, strong) NSString *description;
#property (nonatomic, strong) NSString *firstName;
#property (nonatomic, strong) NSString *lastName;
#property (nonatomic, strong) NSString *activatedTill;
#property (nonatomic, strong) NSString *birthdate;
#property (nonatomic, strong) NSString *phone;
#property (nonatomic, strong) NSString *id;
#property (nonatomic, strong) NSString *statusCode;
#end
JSON string
NSString* str = #"\
{\
\"description\": \"None\",\
\"firstName\": \"vikas\",\
\"lastName\": \"bansal\",\
\"activatedTill\": \"2016-01-17 09:04:11\",\
\"email\": \"bansal\",\
\"birthdate\": \"None\",\
\"phone\": \"None\",\
\"id\": \"1053\",\
\"statusCode\": \"1600\"\
}\
";
Parsing
CustomerDetailsModel* c = [[CustomerDetailsModel alloc] initWithString:str error:nil];
PROBLEM
The problem is that some time when json does not contain a variable that exists in MODEL Why?? becuase the REST API I am using does not render variable into JSON if there is no value in it.
For an example suppose there is no value in birthdate then it will not be included in JSON so when I will try to parse the JSON what I will get is an error.
Please help or please suggest what should I do
Note: I have already gone far ahead with JsonModelLib so if you asking me to use something else or some other lib then I will be a great pain for me. Please please please try to suggest something without changing the lib if it is possible
Many many thanks...
Use an optional model property - there's an example in the repo's README.
https://github.com/icanzilb/JSONModel#optional-properties-ie-can-be-missing-or-null
I have an objects like the below structure: Transaction has an array of Items. Item has an array of SubItems
#interface Transaction : NSObject
#property (nonatomic, copy) NSString *id;
#property (nonatomic, assign) NSInteger status;
#property (nonatomic, strong) NSArray *items; // array of Item
#end
#interface Item : NSObject
#property (nonatomic, copy) NSString *identifier;
#property (nonatomic, assign) NSInteger price;
#property (nonatomic, strong) NSArray *subitems;
#end
#interface SubItem : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, assign) NSInteger price;
#end
I would like to create predicate to find name and price of Subitem from NSArray of Transaction
pred = [NSPredicate predicateWithFormat:
#"ANY SELF.%K.%K.%K contains %#",
#"items",
#"subitems",
#"name",
#"MY_SUB_ITEM_NAME"];
This generates the error below.
failed: caught "NSInvalidArgumentException", "Can't do regex matching
on object (
MY_SUB_ITEM_NAME )."
However when I use the similar format to find out properties in Transaction. It works fine.
pred = [NSPredicate predicateWithFormat:
#"SELF.%K LIKE %#",
#"identifier",
#"TX001"];
How should I correct my predicate to query property in Item and SubItem
I think that cannot work with -predicateWithFormat: for two aggregation levels. On each level you can have a ANY or an ALL aggregation. So the "right" syntax would be ANY items ANY subitems.… = …. Or ANY items ALL subitems.…= …" or …
You can try to build the predicate manually with NSExpression, probably using subqueries.
Oh, you are not using Core Data, what I assumed. So simply do it manually in a loop or use a computed property.
Let us say I have an NSObject Class Person.
#interface Person : NSObject
#property NSString *id;
#property NSString *name;
#property Address *billingAddress;
#end
#interface Address : NSObject
#property NSString *lane;
#property NSString *country;
#property NSString *zip;
#end
Now when I fetch the response from a URL, the response is in the form:
{
"response":
{
"Persons":[{"id":"2232","name":"John","Address":{"lane":"Adelaide Avenue","country":"Canada","zip":"45503"}}{"id":"3422","name":"Jane","Address":{"lane":"Victoria Avenue","country":"Australia","zip":"34903"}}]
}
}
I want to parse the response directly into objects without having to write a method to read and assign objects from NSDictionary. Is there are no objects to parse directly from the response to Object based on the Object parameters similar to "GSon" in Android.
EDIT:
I have used the below code to have generic class that does the job for strings without having to know about the object itself.
for (NSString *key in [dct allKeys]) {
if ([cat respondsToSelector:NSSelectorFromString(key)]) {
[cat setValue:[dct valueForKey:key] forKey:key];
}
}
There is no such magic, not even in Android's GSon!!!
Some where down the line you need to write code for converting JSON to your object.
You may create a generic class, or a method (just once) to convert all dictionary values to your object.
After some digging I did get a JSON framework that does exactly what I wanted - JSONModel.
We just need to specify Models and relationships and all the logic for converting JSON response to the models is handled by the framework. Very handy.
Basic usage :
Consider you have a JSON response like
{"id":"10", "country":"Germany", "dialCode": 49, "isInEurope":true}
The corresponding model will be
#import "JSONModel.h"
#interface CountryModel : JSONMode
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* country;
#property (strong, nonatomic) NSString* dialCode;
#property (assign, nonatomic) BOOL isInEurope;
#end
We don't need to write additional code in the .m file to parse and assign values to the variables. Now to initialise the model from the response we just need to do the below
NSString* json = (fetch JSON here)
NSError* err = nil;
CountryModel* country = [[CountryModel alloc] initWithString:json error:&err];
The works well with complex data structures as well.
Trying to store value in NSDictionary and retrieve it
Objects
#import <Foundation/Foundation.h>
#class ATTTEstOBJ;
#interface ATTTEst : NSObject
#property (nonatomic, retain) NSString *string1;
#property (nonatomic, retain) NSString *string2;
#property (nonatomic, retain) ATTTEstOBJ *obj1;
#end
#interface ATTTEstOBJ : NSObject
#property (nonatomic, retain) NSString *string3;
#property (nonatomic, retain) NSString *string4;
#property (nonatomic, retain) NSString *array1;
#end
I know it needs to be encoded properly to save and retrieve values.but In this case it is a composite object and I have no idea, how to deal it with.
- (void) encodeWithCoder: (NSCoder *)coder
So TLDR , How to save the composite value into dictionary and retrieve it back
I want to store ATTTest into a dictionary and retrieve it back.
EDIT : Detailed explanation
ATTTEst *test=[[ATTTEst alloc]init];
test.string1=#"a";
test.string2=#"b";
ATTTEstOBJ *obj=[[ATTTEstOBJ alloc]init];
obj.string3=#"c";
obj.string4=#"d";
test.obj1=obj;
NSMutableDictionary *dict=[[NSMutableDictionary alloc]initWithCapacity:3];
[dict setObject:test forKey:#"test"];
NSLog(#"%#",dict);
ATTTEst *tester=[dict objectForKey:test];
NSLog(#"%#",tester.obj1.string3);
IT shows null.as output I want to get the value as c for tester.obj1.string3
ATTTEst *tester=[dict objectForKey:test];
should be
ATTTEst *tester=[dict objectForKey:#"test"];
You have used the object test (instead of the string #"test") as key when retrieving the object. I don't think that
was intentionally.
In order to store them into NSDictionary, you don't need to encode them.
Just do:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:, attestObject,#"attestObject", attest2Object,#"atttest2" nil];
Where attestObject and attest2Object are the objects you want to store, and strings are their keys.
This has nothing to do with encoding...
This question already has an answer here:
why is my code outputting *nil description*
(1 answer)
Closed 10 years ago.
Here is my custom class:
ClassA.h
#interface ClassA : NSObject<RKRequestDelegate>{
NSString *uri;
NSString *folderUri;
NSInteger idFolder;
NSString *kind;
bool isMine;
CustomUser *owner;
NSMutableArray *usersAdministrators;
NSMutableArray *usersContributors;
NSMutableArray *usersReaders;
NSString *visibility;
NSString *name;
NSString *description;
NSMutableArray *comments;
}
#property (nonatomic,copy) NSString *uri;
#property (nonatomic,copy) NSString *folderUri;
#property (nonatomic,assign) NSInteger idFolder;
#property (nonatomic,copy) NSString *kind;
#property (nonatomic,assign) bool isMine;
#property (retain) DMIUser *owner;
#property (nonatomic,copy) NSMutableArray *usersAdministrators;
#property (nonatomic,copy) NSMutableArray *usersContributors;
#property (nonatomic,copy) NSMutableArray *usersReaders;
#property (nonatomic,copy) NSString *visibility;
#property (nonatomic,copy) NSString *name;
#property (nonatomic,copy) NSString *description;
#property (nonatomic,copy) NSMutableArray *comments;
#end
ClassA.m
#implementation ClassA
#synthesize uri,folderUri,idFolder,kind,isMine,owner,usersAdministrators,usersContributors,usersReaders,visibility,name,description,comments;
-(NSString*)description {
return #"ClassA";
}
#end
Quite simple. But when i try to create new instance of this, like this:
datas = [NSMutableArray array]; // Tried with [[NSMutableArray alloc] init] => same thing
ClassA *classA = [[ClassA alloc] init];
[datas addObject:classA];
NSLog(#"classA = %#",classA);
NSLog(#"datas = %#",datas);
First NSLog returns "ClassA".
Second NSLog returns "datas = ()"
What's wrong here? I always created class like this and i've never had problem like this.
Thanks!
Ok guyzzz i found the problem. It's my attribute:
NSString *description;
Seems that iOs doesn't love that. It conflict with the -description method in NSObject...
After that, i found a similar question here:
Why can't I use "description" as an attribute name for a Core Data entity?
Cheers
if your want to return some value implement method description in the ClassA
- (NSString *)description {
return #"ClassA";
}
You've got everything you need. Are you sure the variable you're assigning to isn't a weak one? All delegate properties are weak, therefore not retaining the object. My guess is that you're doing something like this
someObject.delegate = [[ClassA alloc] init];
NSLog(#"%#", someObject.delegate);
Because the delegate property is weak it doesn't hold onto the variable.
Edit:
This whole answer assumes you are using ARC. If not, disregard.