Serialize custom object to JSON which contains NSMutableArray - ios

I'm trying to serialize my Cart object which has an NSMutableArray of items in it but getting an:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Item)'
If I'm understanding how this is supposed to work, I need to create an Array of Dictionaries in order for NSJSONSerialization to work correctly. Is that not what I am doing below?
My Cart.h:
#interface Cart : BaseObject
#property (nonatomic, strong) NSString *comp;
#property (nonatomic, strong) NSString *sono;
#property (nonatomic, strong) NSString *cust;
#property (nonatomic, strong) NSString *scus;
#property (nonatomic, strong) NSString *cnid;
#property (nonatomic, strong) NSString *dldt;
#property (nonatomic, strong) NSString *whse;
#property (nonatomic, strong) NSString *pono;
#property (nonatomic, strong) NSString *pon2;
#property (nonatomic, strong) NSString *emad;
#property (nonatomic, strong) NSString *pkin;
#property (nonatomic, strong) NSString *comt;
#property (nonatomic, strong) NSString *rtin;
#property (nonatomic, strong) NSString *lbfg;
#property (nonatomic, strong) NSString *containsOpenPriced;
#property (nonatomic, strong) NSString *totalProductAmount;
#property (nonatomic, strong) NSMutableArray *items;
#property (nonatomic) BOOL *isSubmitting;
#end
My Cart.m:
#implementation Cart
#synthesize comp;
#synthesize sono;
#synthesize cust;
#synthesize scus;
#synthesize cnid;
#synthesize dldt;
#synthesize whse;
#synthesize pono;
#synthesize pon2;
#synthesize emad;
#synthesize pkin;
#synthesize comt;
#synthesize rtin;
#synthesize lbfg;
#synthesize containsOpenPriced;
#synthesize totalProductAmount;
#synthesize items;
- (id) initWithDictionary:(NSDictionary *)dictionary {
self = [super init];
if (self) {
self.comp = dictionary[#"comp"];
self.sono = dictionary[#"sono"];
self.cust = dictionary[#"cust"];
self.scus = dictionary[#"scus"];
self.cnid = dictionary[#"cnid"];
self.dldt = dictionary[#"dldt"];
self.whse = dictionary[#"whse"];
self.pono = dictionary[#"pono"];
self.pon2 = dictionary[#"pon2"];
self.emad = dictionary[#"emad"];
self.pkin = dictionary[#"pkin"];
self.comt = dictionary[#"comt"];
self.rtin = dictionary[#"rtin"];
self.lbfg = dictionary[#"lbfg"];
self.containsOpenPriced = dictionary[#"containsOpenPriced"];
self.totalProductAmount = dictionary[#"totalProductAmount"];
NSArray *itemsArray = dictionary[#"items"];
NSMutableArray *itemsMutableArray = [[NSMutableArray alloc]init];
for (NSDictionary *itemDictionary in itemsArray) {
Item *item = [[Item alloc] initWithDictionary:itemDictionary];
[itemsMutableArray addObject:item];
}
self.items = itemsMutableArray;
}
return self;
}
#end
My code for serializing my object:
NSMutableArray *itemsToSerialize = [[NSMutableArray alloc] init];
for (Item *item in cart.items) {
NSMutableDictionary *itemDict = [[NSMutableDictionary alloc] init];
[itemDict setObject:item forKey:#"item"];
[itemsToSerialize addObject:item];
}
NSMutableDictionary *data = [#{
#"comp" : cart.comp,
#"rtin" : cart.rtin,
#"pono" : cart.pono,
#"pon2" : cart.pon2,
#"totalProductAmount" : totalProductAmount,
#"sono" : cart.sono,
#"emad" : cart.emad,
#"lbfg" : lbfg,
#"pkin" : cart.pkin,
#"containsOpenPriced" : containsOpenPriced,
#"cnid" : cart.cnid,
#"whse" : cart.whse,
#"scus" : cart.scus,
#"dldt" : cart.dldt,
#"cust" : cart.cust,
#"comt" : cart.comt,
#"items": itemsToSerialize
} mutableCopy];
NSString *command = #"shoppingCart.update";
NSMutableDictionary *request = [#{
#"command" : command,
#"comp" : cart.comp,
#"cnid" : sessionController.operator.cnid,
#"cust" : cart.cust,
#"data" : data
} mutableCopy];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:request options:kNilOptions error:nil];
This dies on the above NSJSONSerialization line. What am I missing?

This line: [itemsToSerialize addObject:item]; should be [itemsToSerialize addObject:itemDict];. The result is that you're trying to serialize an array of the items themselves, which gives the exception you're seeing.

NSJSONSerialization only works on arrays (NSArray or NSMutableArray), dictionaries (NSDictionary or NSMutableDictionary, strings (NSString or NSMutableString), and NSNumber.
The common mechanism is to create a - (NSDictionary *)serialize method on your class that copies all its values into a dictionary to be passed into NSJSONSerialization. Then implement - (id)initFromSerialization:(NSDictionary *)serialization to deserialize the object.

I know this is kinda late but maybe this class can ease your coding:
Its a class that transform Custom NSObject to JSON readable object(NSArray or NSDictionary). Have a try and see. It has the capability to skip properties and changed property type from string to NSInteger or Float, it can also changed the final output property name lets say
CustomObject *X;
X.property1 = #"Test";
//and the output JSON readable format you want tot change X to Y
//CustomObject converted to readable format
{Y = #"Test"}
here is the class Disassembler

Related

retrieve RLMObject where value exist in RLMArray<RLMString*> in iOS

i create Stock_RLM : RLMObject and Stock_RLM have RLMArray of RLMString.
i want filer RLMObject using RLMArray's Value. It's Possible?
#import <Realm/Realm.h>
#interface Stock_RLM : RLMObject
#property NSString *_id;
#property NSString *code;
#property NSString *name;
#property NSString *full_name;
#property NSString *type;
#property RLMArray<RLMString> *stock_sectors;
#end
RLM_ARRAY_TYPE(Stock_RLM)
My RLMObject is : -
Stock_RLM {
_id = 5b60554726f2fe334cad881d;
code = GRASIM;
name = GRASIM;
full_name = Grasim Industries Limited;
type = NSE;
stock_sectors = RLMArray<string> <0x1c4114d00> (
[0] 5b6046d1f1e8972b9cebd584,
[1] 5b6046d1f1e8972b9cebd586,
[2] 5b6046d1f1e8972b9cebd587,
[3] 5b6046d1f1e8972b9cebd588,
[4] 5b6046d1f1e8972b9cebd59a,
[5] 5b6046d1f1e8972b9cebd5c1
);
}
i Want to filter '5b6046d1f1e8972b9cebd584'exist in RLMArray in RLMObject or Not.
in your **.h
#interface TESTClass:NSObject
#property NSString *_id;
#property NSString *_code;
#property NSString *_name;
#property NSArray *theStrArr;
#end
in your **.m
#implementation TESTClass
#end
in somewhere you test
TESTClass *obje1 = [[TESTClass alloc] init];
TESTClass *obje2 = [[TESTClass alloc] init];
TESTClass *obje3 = [[TESTClass alloc] init];
obje1.theStrArr = [NSArray arrayWithObjects:#"11",#"22",#"33",nil];
obje2.theStrArr = [NSArray arrayWithObjects:#"44",#"55",#"66",nil];
obje3.theStrArr = [NSArray arrayWithObjects:#"77",#"88",#"99",nil];
NSArray *totalArr = [NSArray arrayWithObjects:obje1,obje2,obje3, nil];
NSString *testStr = [NSString stringWithFormat:#"22"];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"theStrArr CONTAINS %#",testStr];
NSArray *resultArr = [totalArr filteredArrayUsingPredicate:pred];
CLog(#"the result arr %#",resultArr);

Creating a data model from JSON

I have a JSON that looks like this :
{
"club": [
{
"titles": "1",
"league": "epl",
"country": "england",
}
}
And I have created a property like this :
#property (strong, nonatomic) NSMutableArray <Clubs> *club;
The club property inherits from the Clubs class which has the titles, leagues and country properties.
When I try to create a dictionary with that data model, I am unable to access the properties inside the club array.
Am I creating the data model incorrectly ?
Creating the dictionary:
for (NSDictionary *dictionary in responseObject) {
if (![self.searchText isEqualToString:#""]) {
self.predictiveProductsSearch = [[PerdictiveSearch alloc]initWithDictionary:dictionary error:nil];
self.predictiveTableView.dataSource = self;
[self.predictiveTableView reloadData];
self.predictiveTableView.hidden = NO;
}
}
Clubs class
#import <JSONModel/JSONModel.h>
#protocol Clubs #end
#interface Clubs : JSONModel
#property (strong, nonatomic) NSString <Optional> * titles;
#property (strong, nonatomic) NSString <Optional> * league;
#property (strong, nonatomic) NSString <Optional> * country;
#property (strong, nonatomic) NSString <Optional> * topGS;
#property (strong, nonatomic) NSString <Optional> * GoalSc;
#property (strong, nonatomic) NSString <Optional> * TransferBudget;
#end
Please use below code to achieve JSON Model saving:
_club = [[NSMutableArray alloc]init];
NSDictionary *responseObject = #{
#"club": #[
#{
#"titles": #"1",
#"league": #"epl",
#"country": #"england"
}]
};
NSArray *newResponseObject = [responseObject objectForKey:#"club"];
for (NSDictionary *dictionary in newResponseObject) {
Clubs *objClubs = [[Clubs alloc]initWithDictionary:dictionary error:nil];
[_club addObject:objClubs];
}
NSLog(#"%#",[_club objectAtIndex:0]);
which print like below :
<Clubs>
[titles]: 1
[country]: england
[GoalSc]: <nil>
[league]: epl
[topGS]: <nil>
[TransferBudget]: <nil>
</Clubs>

How can I store array values (RLMArray) in Realm DB with Objective C?

How can I store array values (RLMArray) in Realm DB ?
My .h file below,
#interface Hotlines : RLMObject
#property (strong, nonatomic) NSString *id;
#property (strong, nonatomic) NSString *department_name;
#property (strong, nonatomic) NSString *flag;
#property (strong,nonatomic) RLMArray<Numbers> *numbers;
#end
You need to create realm model for Numbers array:
#import <Realm/Realm.h>
// Define your models for Numbers array
#interface Numbers : RLMObject
#property NSInteger *num;
#property (strong, nonatomic) NSString *name;
#end
RLM_ARRAY_TYPE(Numbers) // define RLMArray< Numbers >
// Define your models for Numbers array
#interface Hotlines : RLMObject
#property (strong, nonatomic) NSString *id;
#property (strong, nonatomic) NSString *department_name;
#property (strong, nonatomic) NSString *flag;
#property (strong,nonatomic) RLMArray<Numbers> *numbers;
#end
// Implementations
#implementation Numbers
#end // none needed
#implementation Hotlines
#end // none needed
For more information refer Realm Objective c
Update :
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
Hotlines *obj = [[Hotlines alloc] init];
obj.department_name = #"anyString";
Numbers *number = [[Numbers alloc] init]
number.num = 1;
[obj.numbers addObject:number]
[realm addObject:obj];
}];
For multiple data :
[realm transactionWithBlock:^{
Hotlines *obj = [[Hotlines alloc] init];
obj.department_name = #"anyString";
for (int i=0; 1< 10; i++) {
Numbers *number = [[Numbers alloc] init]
number.num = i;
number.name = #"XYZ"
[obj.numbers addObject:number]
}
[realm addObject:obj];
}];
Can be done with primitives if you really just want numbers:
#interface Hotlines : RLMObject
#property NSString *id;
#property NSString *department_name;
#property NSString *flag;
#property RLMArray<NSNumber*><RLMFloat> *numbers;
#end
From the realm docs:
RLMArrays can store primitive values in lieu of Realm objects. In
order to do so, constrain a RLMArray with one of the following
protocols: RLMBool, RLMInt, RLMFloat, RLMDouble, RLMString, RLMData,
or RLMDate
.

IOS/Objective-C: Error Converting JSON to Object

I am trying to convert JSON array to object for display in table. I am able to capture JSON. However, when I try to turn into object, I get error shown below. There is definitely a property named "name" in object class.
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSMutableArray* latestItems = nil;
latestItems = [[NSMutableArray alloc] init];
latestItems = [json objectForKey:#"items"];
[self.tableView reloadData];
for (int i = 0; i < latestItems.count; i++)
{
NSDictionary *itemElement = latestItems[i];
// Create a new l object and set its props to todoElement properties
IDItemFromServer *newItem = [[IDItemFromServer alloc] init];
//ERROR NEXT LINE THROWS FOLLOWING ERROR
//'NSUnknownKeyException', reason: '[<IDItemFromServer 0x14e88010> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key name.'
[newItem setValue:#"hi" forKey:#"name"];
[newItem setValue:itemElement[#"address"] forKey:#"address"];
// Add this new item to the array
[latestItems addObject:newItem];
}
Would appreciate any suggestions on how to fix error.
Edit:
//Object.h file
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface IDItemFromServer : NSObject
#property (nonatomic, retain) NSNumber * iid;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * address;
#end
It says IDItemFromServer has no property name. add the name,address property like bellow code
In IDItemFromServer.h file
#import <Foundation/Foundation.h>
#interface IDItemFromServer : NSObject
#property(nonatomic,strong) NSString name;
#property(nonatomic,strong) NSString address;
#end
In IDItemFromServer.m file
#import "IDItemFromServer.h"
#implementation IDItemFromServer
#synthesize name;
#synthesize address;
#end

Can't store object in array

This is Apprecord class
#interface AppRecord : NSObject
#property (nonatomic, strong) NSString *appIcon;
#property (nonatomic, strong) NSString * name;
#property (nonatomic, strong) NSString * description;
#property (nonatomic, strong) NSString * location;
#property (nonatomic, strong) NSString * address;
#property (nonatomic, strong) NSString * contacts;
#property (nonatomic, strong) NSString * additional_info;
#property (nonatomic, strong) NSString * image;
#end
and I am parsing json adding to an object of App record class
#import "ParserClass.h"
#import "AppRecord.h"
#interface ParserClass ()
#property (nonatomic, strong) NSArray *appRecordList;
#property (nonatomic, strong) NSData *dataToParse;
#property (nonatomic, strong) NSMutableArray *workingArray;
#property (nonatomic, strong) AppRecord *workingEntry;
#property (nonatomic, strong) NSMutableString *workingPropertyString;
#property (nonatomic, strong) NSArray *elementsToParse;
#property (nonatomic, readwrite) BOOL storingCharacterData;
#end
#implementation ParserClass
- (id)initWithData:(NSData *)data
{
self = [super init];
if (self != nil)
{
_dataToParse = data;
}
return self;
}
- (void)main
{
self.workingArray = [NSMutableArray array];
self.workingPropertyString = [NSMutableString string];
self.workingArray=[[NSMutableArray alloc]init];
NSDictionary *allData=[NSJSONSerialization JSONObjectWithData:_dataToParse options:0 error:nil];
NSLog(#"%#",allData);
for (NSDictionary *dict in allData)
{
NSLog(#"dict====%#",dict);
self.workingEntry=[[AppRecord alloc]init];
self.workingEntry.name=[dict objectForKey:#"name"];
self.workingEntry.description=[dict objectForKey:#"description"];
self.workingEntry.location=[dict objectForKey:#"location"];
self.workingEntry.address=[dict objectForKey:#"address"];
self.workingEntry.contacts=[dict objectForKey:#"contacts"];
self.workingEntry.additional_info=[dict objectForKey:#"additional_info"];
self.workingEntry.image=[dict objectForKey:#"image"];
[self.workingArray addObject:self.workingEntry];
}
NSLog(#"WORKING ARRAY========%#",self.workingArray);// Not getting proper value of working array
self.workingArray = nil;
self.workingPropertyString = nil;
self.dataToParse = nil;
}
#end
My problem is not getting proper value of working array,it only stores description property,but it should store apprecord object,please help.
OUTPUT
alldata=
(
{
"additional_info" = "lOREN iPSUM";
address = "1972 Hillview St. Sarasota,FL 34239";
contacts = 8745674556;
description = "Very cute place, awesome wait staff, great food. I am here on vacation and it was an awesome place to go to after a day relaxing at the beach.";
id = 1;
image = "http://..";
location = "1972 Hillview St. Sarasota,FL 34239";
name = "Beer Tasting at Hurricane Hanks";
},
{
"additional_info" = gdfgdfg;
address = "Farrer Place, Sydney, New South Wales, Australia";
contacts = 3423423423423;
description = restataurant;
id = 16;
image = "http://..";
location = kolkata;
name = "mosco ";
}
)
WORKING ARRAY========(
"Very cute place, awesome wait staff, great food. I am here on vacation and it was an awesome place to go to after a day relaxing at the beach.",
restataurant
)
First object name== Beer Tasting at Hurricane Hanks
First you remove 2 time intialization of self.workingArray
And please replace
#property (nonatomic, strong) NSString * description;
deccription with some other name
To know the reason click this link
for (NSDictionary *dict in allData)
{
AppRecord *createAppRecord=[[AppRecord alloc]init];
//Do some thing
[self.workingArray addObject:createAppRecord];
}
I think it will be helpful to you.

Resources