How can I create a ConvertOnDemand 'NSArray *' using the JSONModel library from the following JSON response: -
[
{"id": 1, "name": "jim"},
{"id": 2, "name": "lovy"}
]
Please check here if you want to know more JSONModel ConvertOnDemand (https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=jsonmodel+convertonDemand).
If you're open to using the native Foundation framework instead, you could do something like this
NSArray *arr = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&err];
If your JSON is in the form of a string, just convert to NSData before calling the above
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
This solution will give you an NSArray of NSDictionaries
May be BWJSONMatcher is what you are looking for.
Declare your data model that matches your json string:
#interface YourDataModel : NSObject
#property (nonatomic, assign) NSInteger id;
#property (nonatomic, strong) NSString *name;
#end
Then your can use BWJSONMatcher to convert the json string to an NSArray which can be directly used in your ViewControllers.
NSArray *jsonArray = [BWJSONMatcher matchJSON:jsonString withClass:[YourDataModel class]];
ConvertOnDemand is optional for your model class, if your entity class is Person class, declare the array property like this,
#property (nonatomic, strong) NSArray<Person, ConvertOnDemand> *persons;
#property (nonatomic, strong) NSArray<Person> *persons;
For the former one, the persons array type is JSONModelArray[Person], it just means all the person object has conformed Person protocol. For the later one, the type is NSArray with unconfirmed objects, but they are really Person type.
Related
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.
I have the json
{"Types":{
"food":[{"cve":"1","description":"Pizza"},{"cve":"2","description":"Restaurant"},{"cve":"3","description":"Cafe"}],
"Health":[{"cve":"3","description":"Pharmacy"},{"cve":"4","description":"Hospital"}]
} }
Types.h
#import <Foundation/Foundation.h>
#interface Types: NSObject
#property (nonatomic, copy) NSDictionary *types;
#end
Types.m
#import "Types.h"
#import <Motis/Motis.h>
#import "SubTipo.h"
#implementation Types
+ (NSDictionary*)mts_mapping
{
return #{#"types": mts_key(types),};
}
#end
Subtype.h
#import <Foundation/Foundation.h>
#interface Subtype: NSObject
#property (nonatomic, assign) int cve;
#property (nonatomic, copy) NSString *description;
#end
Subtype.m
#import "Subtype.h"
#import <Motis/Motis.h>
#implementation Subtype
+ (NSDictionary*)mts_mapping
{
return #{#"cve": mts_key(cve),
#"description": mts_key(description),
};
}
#end
I deserialize with
Types * values=[[Types alloc]init];
NSDictionary * jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
[values mts_setValuesForKeysWithDictionary:jsonObject ];
I get NSDictionary with NSArray of NSDictionary
but I need NSDictionary with NSArray of Subtypes
I try with
+ (NSDictionary*)mts_arrayClassMapping
{
return #{mts_key(types): Subtype.class};
}
but wasn't successful
How can I get these with Motis
As far as I see, your Types object is not properly defined. If you have an attribute of type NSDictionary* and the JSON received is a Dictionary, Motis won't perform any automatic conversion as the types already match (you are receiving a dictionary and your attribute is of type NSDictionary).
Therefore, you must implement your Type object following your JSON structure. This means that your Type object must have two properties of type array, one for food and one for health. Then, using the method +mts_arrayClassMapping you can specify the content type of the arrays to Subtype.
Here the implementation:
// ***** Type.h file ***** //
#interface Type: NSObject
#property (nonatomic, strong) NSArray *food;
#property (nonatomic, strong) NSArray *health;
#end
// ***** Type.m file ***** //
#implementation Type
+ (NSDictionary*)mts_mapping
{
return #{#"food": mts_key(food),
#"Health": mts_key(health),
};
}
+ (NSDictionary*)mts_arrayClassMapping
{
return #{mts_key(food): Subtype.class,
mts_key(health): Subtype.class,
};
}
#end
Regarding the implementation of Subtype, yours is already correct. However, you should not use the property name description as it is already being used by NSObject:
// ***** Subtype.h file ***** //
#interface Subtype: NSObject
#property (nonatomic, assign) NSInteger cve;
#property (nonatomic, copy) NSString *theDescription;
#end
// ***** Subtypes.m file ***** //
#implementation Subtype
+ (NSDictionary*)mts_mapping
{
return #{#"cve": mts_key(cve),
#"description": mts_key(theDescription),
};
}
#end
Finally, as you list above, you can map your JSON, but first you will have to extract the "dictionary" for key Types, which you will map to your "Type" model object.
// Get the json data
NSDictionary * jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
// Extract the JSON dictionary of types.
NSDictionary *jsonType = [jsonObject objectForKey:#"Types"];
// Create a Type object
Type *type = [[Type alloc] init];
// Map JSON contents to the type object with Motis
[type mts_setValuesForKeysWithDictionary:jsonType];
Hoping this fixes your issue.
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...
Maybe there's a similar question here, but I could not find it. So I have the RestKit 0.2pre4 and want to map such JSON ...
{
"location": {
"position": {
"latitude": 53.9675028,
"longitude": 10.1795594
}
},
"id": "da3224f2-5919-42f2-9dd8-9171088f4ad7",
"name": "Something even more beautiful",
}
... to such an object:
#interface FavoritePlace : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * placeId;
#property (assign, nonatomic) double latitude;
#property (assign, nonatomic) double longitude;
#end
As you can see, the point is that I don't want to create a relationship and store "Location" object in database separately - it just doesn't make sense. Therefore I want to assign those nested things (location.position.latitude and location.position.longitude) to particular properties of object itself. How to achieve that?
Apparently, I did a wild ass guess and it worked! Here's the mapping which does the trick:
[placeMapping addAttributeMappingsFromDictionary:#{
#"id": #"placeId",
#"name": #"name",
#"location.position.latitude": #"latitude",
#"location.position.longitude": #"longitude"
}];
Have not found this in documentation, but maybe it's just me... Anyway, if something logical, but undocumented, works, then framework should be good. :) RestKit FTW!
You can pass the string containig the json string to nsdata with
NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
Then, you will be able to parse de json data with the iOS API with
NSError *error;
NSDictionary *json = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error] : nil;
Now, examine the generated NSDictionary (with NSlog for example), fill your 'FavoritePlace' object and persist it.
Hope helps!
I have a PHP Webservice that returns a JSON string with this format:
[{"latitud":"37.995914","longitud":"-1.139705","nombre":"Miguel de
Unamuno"},{"latitud":"37.995433","longitud":"-1.140143","nombre":"Calle
Pina"},{"latitud":"37.99499","longitud":"-1.140361","nombre":"Calle
Moncayo"},{"latitud":"37.993918","longitud":"-1.139392","nombre":"Calle
Moncayo2"},{"latitud":"37.994588","longitud":"-1.138543","nombre":"Calle
Salvador de Madriaga"}]
In my project, I have a custom class with the next structure:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface PCoordenada : NSObject
#property (nonatomic) CLLocationCoordinate2D *punto;
#property (nonatomic,strong) NSString *nombre;
#end
Then, I´m using other class for the main app:
#import <UIKit/UIKit.h>
#import "PCoordenada.h"
#interface TestViewController : UIViewController
#property (nonatomic,strong) NSData * HTTPResponse;
#property (nonatomic,strong) NSDictionary * dic;
#property (nonatomic,strong) NSMutableArray *arrayCoord;
#property (nonatomic,strong) PCoordenada *coor;
-(IBAction)GetDataFrom:(id)sender;
#end
I wonder how I can make a array of PCoordenada's objects that contain the info of JSON string.
Anyone could help me?
Thanks in advance :)
Do this:
NSData *theData = [NSData dataWithContentsOfURL:[NSURL URLWithString:YOUR_URL]];
NSArray *arrRequests = [NSJSONSerialization JSONObjectWithData:theData options:NSJSONReadingMutableContainers error:nil];
which will put the JSON into an NSArray of objects. Each of these objects is an NSDictionary. So then you just need to loop through the NSArray to get out the NSDictionary of each.
//now let's loop through the array and generate the necessary annotation views
for (int i = 0; i<= arrRequests.count - 1; i++) {
//now let's dig out each and every json object
NSDictionary *dict = [arrRequests objectAtIndex:i];}
Each NSDictionary that you get from the loop holds the JSON properties as a key in the NSDictionary:
NSString *address = [NSString stringWithString:[dict objectForKey:#"Address"]];
It's also a good practice to use multithreading when reading JSON for better performance.
This article has a very simple to follow how-to. I recommend a read.