How to create objects from JSON NSDictionary - ios

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.

Related

JSONModel NSArray ConvertOnDemand

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.

NSManagedObject shared properties

I have just set up a simple Core Data database, and I have created a few entities with some properties. However some entities have some properties in common, like the Date parameter. Until now I do something like:
NSManagedObject * passedObject...
if ([_passedObject.entity.name isEqual:#"Archive"]){
Archive* fileObject = (Archive *)_passedObject;
myDictionary = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:fileObject.fileData];
}else{
AllFiles* fileObject = (AllFiles *)_passedObject;
myDictionary = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:fileObject.fileData];
}
fileData is common to both, so I would like just to be doing passedObject.fileData instead of casting the types. Can this be done?
define a protocol...
#protocol FileDataProvider
#property (strong,nonatomic) NSData* fileData;
//or -(NSData *)fileData; would be suitable for RO access
#end
and make your objects conform to that protocol
#interface Archive:NSManagedObject< FileDataProvider >
#property (strong,nonatomic) NSData* fileData;
#end
#interface AllFiles:NSManagedObject< FileDataProvider >
#property (strong,nonatomic) NSData* fileData;
#end
thus you can cast like so
myDictionary = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:((id<FileDataProvider>)passedObject).fileData];
or safer
if([passedObject conformsToProtocol:#protocol(FileDataProvider)]) {
myDictionary = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:((id<FileDataProvider>)passedObject).fileData];
}

How to get Custom Objects from JSON in Xcode?

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.

MOTIS Object Mapping, With NSDictionary with values NSArray how can I specify type of array elements?

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.

NSDictionary custom object store and retrieve

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...

Resources