Objective C serialize a collection to JSON/XML - objective-c

I have a classes looking like this:
#interface AISlideItem: NSObject <NSCoding>
{
NSString* PlaceHolderName;
NSInteger PlaceHolderID;
}
#property (nonatomic, strong) NSString* PlaceHolderName;
#property (nonatomic) NSInteger PlaceHolderID;
#end
#interface AITitleSlideItem : AISlideItem
{
NSString* Title;
}
#property (nonatomic, strong) NSString* Title;
#end
#interface AIParagraphSlideItem : AISlideItem
{
NSMutableArray* Paragraphs;
}
#property (nonatomic, strong) NSMutableArray* Paragraphs;
#end
#interface AITextSlideItem : AISlideItem
{
NSString* Text;
}
#property (nonatomic, strong) NSString* Text;
#end
#interface AIPictureSlideItem : AISlideItem
{
NSMutableData* Picture;
}
#property (nonatomic, strong) NSMutableData* Picture;
#end
#interface AISlideContent : NSObject
{
NSString* LayoutName;
NSMutableArray* Items;
}
#property (nonatomic,strong) NSString* LayoutName;
#property (nonatomic,strong) NSMutableArray* Items;
#end
#interface ContentParaghraph : NSObject
{
NSInteger Level;
NSString* Text;
}
#property (nonatomic) NSInteger Level;
#property (nonatomic, strong) NSString* Text;
#end
I create a complex collection from these classes like this:
NSMutableArray* l = [[NSMutableArray alloc]init ];
AITitleSlideItem* tis1 = [[AITitleSlideItem alloc]init];
[tis1 setPlaceHolderName:#"I don't think we're using this..."];
[tis1 setPlaceHolderID:1];
[tis1 setTitle:#"This is a title"];
AITextSlideItem* tes1 = [[AITextSlideItem alloc]init];
[tes1 setPlaceHolderName:#"I don't think we're using this..."];
[tes1 setPlaceHolderID:2];
[tes1 setText:#"This is the description"];
AISlideContent* slide1 = [[AISlideContent alloc]init];
[slide1 setLayoutName:#"Title content"];
[[slide1 Items]addObject:tis1];
[[slide1 Items]addObject:tes1];
[l addObject:slide1];
[l addObject:slide1];
What i want to to serialize the NSMutableArray l into any portable format like json or xml.
Could you please post some code doing so?
Sincerely
Zoli

After further investigation i found nothing more suitable for my needs.
I decided to learn a bit more about JSON and create a function that creates the JSON structure manually. Even if it took 2-3 hours, it did worth all the effort.

Related

Objective-C class representing JSON

I am new to RestKit and an Objective-C newbie. The JSON that I would like to turn into Objective-C objects has the following format.
{
"id":1,
"ron95":700.0,
"ron92":700.0,
"dieselNormal":700.0,
"dieselSpecial":700.0,
"postDate":1435465383000
}
In Java, the JSON would be represented like this:
public class Price {
private Long id;
private Double ron95;
private Double ron92;
private Double dieselNormal;
private Double dieselSpecial;
private java.util.Date postDate;
...
}
What would the mapping Objective-C class be like and how would you do the mapping using RestKit?
Edit: This is what I think my Objective-C representation should look like. Correct me if I am wrong.
Price.h
#import <Foundation/Foundation.h>
#interface Price : NSObject {
NSInteger id;
double ron95;
double ron92;
double dieselNormal;
double dieselSpecial;
NSDate *postDate;
}
#property (nonatomic) NSInteger id;
#property (nonatomic) double ron95;
#property (nonatomic) double ron92;
#property (nonatomic) double dieselNormal;
#property (nonatomic) double dieselSpecial;
#property (nonatomic, retain) NSDate *postDate;
#end
Price.m
#import "Price.h"
#implementation Price
#synthesize id;
#synthesize ron95;
#synthesize ron92;
#synthesize dieselNormal;
#synthesize dieselSpecial;
#synthesize postDate;
#end
I have been looking into this for a while. I decided to write my own solution. It is very simple and built upon existing Apple functionality. Just go to github and copy the source to your project. Have your Price class inherit from GSObject instead of NSObject.
Write a category for NSDate class with this class method:
+(id) initWithJsonValue:(NSString*)jsonValue
Here is where you would convert the date string
"postDate":1435465383000
to an NSDate probably using a date formatter.
See here: https://github.com/gslinker/GSObject
And here: http://digerati-illuminatus.blogspot.com/2016/01/objective-c-and-json-convert-subclass.html
Here is a sample that I made, notice it has an NSDate object as well.
For your data model object have it inherit from GSObject instead of NSObject. Here is an example of ThingOne with inherits from GSObject:
ThingOne* object1 = [[ThingOne alloc] init];
object1.name = #"John Jones";
NSData* jsonData1 = [object1 toJsonDataWithOptions:NSJSONWritingPrettyPrinted];
NSString *jsonString1 = [object1 toJsonStringWithOptions:NSJSONWritingPrettyPrinted];
NSDictionary<NSString *,id> *dict1 = [GSObject dictionaryWithValues:object1];
NSString *roundTripJson1 = [object1 toJsonStringWithOptions:NSJSONWritingPrettyPrinted];
//
// ThingOne.h
// JasonStuff
//
// Created by Geoffrey Slinker on 12/28/15.
// Copyright © 2015 Slinkworks LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GSObject.h"
#import "ThingTwo.h"
#interface ThingOne : GSObject
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) ThingTwo *thingTwo;
#property (nonatomic, retain) NSArray *values;
#property (nonatomic, retain) NSDictionary *dict;
#property int myInt;
#property float myFloat;
#property BOOL myBool;
#property (nonatomic, retain) NSNumber* someMoney;
#end
//
// ThingOne.m
// JasonStuff
//
// Created by Geoffrey Slinker on 12/28/15.
// Copyright © 2015 Slinkworks LLC. All rights reserved.
//
#import "ThingOne.h"
#implementation ThingOne
#synthesize name;
#synthesize thingTwo;
#synthesize values;
#synthesize dict;
#synthesize myInt;
#synthesize myFloat;
#synthesize myBool;
#synthesize someMoney;
- (instancetype)init
{
self = [super init];
thingTwo = [[ThingTwo alloc] init];
thingTwo.stuff = #"Thing Two Stuff";
thingTwo.someOtherStuff = #"Thing Two Other Stuff";
NSDateFormatter *dateFormater = [[NSDateFormatter alloc]init];
[dateFormater setDateFormat:#"yyyy-mm-dd"];
thingTwo.someDate = [dateFormater dateFromString:#"1963-10-07"];
values = [NSArray arrayWithObjects:#"Value1", #"Value2", #"Value3", nil];
dict = [NSDictionary dictionaryWithObjectsAndKeys:#"value1", #"key1", #"value2", #"key2", nil];
myInt = 5431;
myFloat = 123.456f;
myBool = YES;
someMoney = [NSNumber numberWithInt:503];
return self;
}
#end
//
// ThingTwo.h
// JasonStuff
//
// Created by Geoffrey Slinker on 12/28/15.
// Copyright © 2015 Slinkworks LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GSObject.h"
#interface ThingTwo : GSObject
#property (nonatomic, retain) NSString *stuff;
#property (nonatomic, retain) NSString *someOtherStuff;
#property (nonatomic, retain) NSDate *someDate;
#property (nonatomic, retain) NSString *nullString;
#property (nonatomic, retain) NSDate *nullDate;
#end
//
// ThingTwo.m
// JasonStuff
//
// Created by Geoffrey Slinker on 12/28/15.
// Copyright © 2015 Slinkworks LLC. All rights reserved.
//
#import "ThingTwo.h"
#implementation ThingTwo
#synthesize stuff;
#synthesize someOtherStuff;
#synthesize someDate;
- (instancetype)init
{
self = [super init];
someDate = [NSDate date];
return self;
}
#end
Here is an example of the JSON output:
{
"values" : [
"Value1",
"Value2",
"Value3"
],
"myInt" : 5431,
"myFloat" : 123.456,
"myBool" : true,
"someMoney" : "$503.00",
"thingTwo" : {
"stuff" : "Thing Two Stuff",
"nullDate" : null,
"someDate" : "1963-01-07 07:10:00 +0000",
"nullString" : null,
"someOtherStuff" : "Thing Two Other Stuff"
},
"name" : "John Jones",
"dict" : {
"key1" : "value1",
"key2" : "value2"
}
}
have a look at https://github.com/icanzilb/JSONModel, from cocoapods
all (de)serialization is handled automatically for you, even complex structures of array of custom objects.
Been using it, been loving it...

NsMutable Array search and conversion

I have mutable array of class like :
#protocol CategoryModel #end
#interface CategoryModel : NSObject
#property (assign) int Id;
#property (strong, nonatomic) NSString* ShortString;
#property (strong, nonatomic) NSString* Description;
#property (strong, nonatomic) NSString* AppId;
#end
I want to get an Nsdata of the AppId , how to do that
and I want to search this NsMutableArry by Id
As far as I understand you want to get data from array by Id. You can use NSPredicate for this:
[myArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"Id == %d", yourID]];

how to initialize a NSMutableOrderedSet

Can someone show me how to initialize an NSMutableOrderedSet?
I tried the following
NSMutableOrderedSet *answerSet = [NSMutableOrderedSet orderedSet];
but hang there an the log is just (lldb)
will insert object Answer
#import "Answer.h"
#import "Survey.h"
#implementation Answer
#dynamic count;
#dynamic text;
#dynamic survey;
#end
EDIT 1:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Survey : NSManagedObject
#property (nonatomic, retain) NSDate * dateCreated;
#property (nonatomic, retain) NSString * id;
#property (nonatomic, retain) NSString * note;
#property (nonatomic, retain) NSString * question;
#property (nonatomic, retain) NSMutableOrderedSet *answers;
#end
#interface Survey (CoreDataGeneratedAccessors)
- (void)addAnswersObject:(NSManagedObject *)value;
- (void)removeAnswersObject:(NSManagedObject *)value;
- (void)addAnswers:(NSMutableOrderedSet *)values;
- (void)removeAnswers:(NSMutableOrderedSet *)values;
#end
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Survey;
#interface Answer : NSManagedObject
#property (nonatomic, retain) NSNumber * count;
#property (nonatomic, retain) NSString * text;
#property (nonatomic, retain) Survey *survey;
#end
NSMutableOrderedSet *answerSet = [[NSMutableOrderedSet alloc] initWithCapacity:4];
Answer *ans1 = [NSEntityDescription insertNewObjectForEntityForName:#"Answer"inManagedObjectContext:managedObjectContext];
ans1.text = trimedAns1;
ans1.count = 0;
ans1.survey = survey;
Answer *ans2 = [NSEntityDescription insertNewObjectForEntityForName:#"Answer"inManagedObjectContext:self.managedObjectContext];
ans2.text = trimedAns2;
ans2.count = 0;
ans2.survey = survey;
[answerSet addObject:ans1];
[answerSet addObject:ans2];
[survey setAnswers:answerSet];
NSError *error = nil;
if (![managedObjectContext save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error userInfo]);
} else {
NSLog(#"Saved question : %#", self.question.text);
}
and now I got exception below when saving to core data:
2013-06-27 22:58:33.955 Simple Survey[718:11903] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-many relationship: property = "answers"; desired type = NSSet; given type = __NSOrderedSetM; value = {(
<Answer: 0x8168070> (entity: Answer; id: 0x81c8880 <x-coredata:///Answer/t0F1038D5-DD97-4066-AB7D-E92386A9010B3> ; data: {
count = nil;
survey = "0x81be560 <x-coredata:///Survey/t0F1038D5-DD97-4066-AB7D-E92386A9010B2>";
text = 6;
}),
<Answer: 0x74ec7f0> (entity: Answer; id: 0x74eed40 <x-coredata:///Answer/t0F1038D5-DD97-4066-AB7D-E92386A9010B4> ; data: {
count = nil;
survey = "0x81be560 <x-coredata:///Survey/t0F1038D5-DD97-4066-AB7D-E92386A9010B2>";
text = 7;
})
)}.'
You can do like this:
NSMutableOrderedSet *answerSet = [[NSMutableOrderedSet alloc] initWithCapacity:100];
And reading this will be helpful to you.

CoreLocation object, can't assign longitude

I'm building an app that works with MapKit and I need to get coordinates from Google Maps.
I made a function that does this (and through debugging I know I get the good coordinates), but it then crashes when I try to assign it to my event object's coordinates.
Below is the code and I've clearly commented with // <---------------- where it fails...
AppDelegate.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "MapViewController.h"
#import "Event.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate, MKMapViewDelegate, CLLocationManagerDelegate>{
CLLocationManager *locationManager;
}
//-(void)makeTestData:(int)amount;
-(void) addressLocation:(NSString*)adres:(Event*)event;
#property (strong, nonatomic) UIWindow *window;
//#property (strong, nonatomic) NSMutableArray *events;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "ListViewController.h"
#import "Event.h"
#import <RestKit/RestKit.h>
#implementation AppDelegate{
NSMutableArray *events;
/* for test data */
NSMutableArray *titles;
}
#synthesize window = _window;
//#synthesize events;
-(void) addressLocation:(NSString*)adres: (Event*)event {
NSString *urlString = [NSString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#&output=csv&key=MYKEY",
[adres stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString]];
NSArray *listItems = [locationString componentsSeparatedByString:#","];
double latitude = 0.0;
double longitude = 0.0;
if([listItems count] >= 4 && [[listItems objectAtIndex:0] isEqualToString:#"200"]) {
latitude = [[listItems objectAtIndex:2] doubleValue];
longitude = [[listItems objectAtIndex:3] doubleValue];
}
else {
//Show error
}
CLLocationCoordinate2D location;
location.latitude = latitude;
location.longitude = longitude; // <----- Checked in debugging, coords are good
event.coordinate.latitude = latitude; // <----- can't assign the latitude here =/
event.coordinate.longitude = longitude; // <----- can't assign the longitude here =/
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// START COMMUNICATOIN WITH REST INTERFACE
//RKClient* client = [RKClient clientWithBaseURL:#"link"];
//NSLog(#"I am your RKClient singleton : %#", [RKClient sharedClient]);
// -------------------TEST OBJECTS
//makeTestData(3);
events = [NSMutableArray arrayWithCapacity:3];
titles = [NSMutableArray arrayWithCapacity:3];
[titles addObject:#"Gent Jazz Festival"];
[titles addObject:#"Over blauw bloed en witte billenbijters - zoektocht in het Prinsenhof (zonder gids)"];
[titles addObject:#"DuveltTent"];
Event *event = [[Event alloc] init];
event.title = [titles objectAtIndex:(rand()*100)%3];
event.description = #"omminommie!!!";
event.zone = #"fzfzefez";
event.gemeente = #"Gent";
event.plaats = #"";
event.straat = #"Sint-Veerleplein";
NSString *adres = [NSString stringWithFormat:#"%#, %#", event.gemeente, event.straat];
[self addressLocation:adres:event]; //<---- This function fails, see above for def
event.zone = #"blub";
[events addObject:event];
...
---- EDIT
Like the code is, as above, it doesn't even compile and gives the error:
Expression is not assignable
When I use = location (which I did before) as suggested above I get the following error:
2012-07-13 17:14:20.608 Zone-It-new[565:707] -[Event setCoordinate:]: unrecognized selector sent to instance 0x283ab0
2012-07-13 17:14:20.621 Zone-It-new[565:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Event setCoordinate:]: unrecognized selector sent to instance 0x283ab0'
*** First throw call stack:
(0x3748488f 0x35189259 0x37487a9b 0x37486a83 0x373e1650 0x6a319 0x6a5c9 0x31190cab 0x3118a7dd 0x31158ac3 0x31158567 0x31157f3b 0x33b9a22b 0x37458523 0x374584c5 0x37457313 0x373da4a5 0x373da36d 0x3118986b 0x31186cd5 0x6a097 0x6a03c)
terminate called throwing an exception
Here are my event.h and event.m
event.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import <RestKit/RestKit.h>
#interface Event : NSObject <MKAnnotation>
// required property from mkanotation
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
// Optional
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *description;
#property (nonatomic, copy) NSString *zone;
#property (nonatomic, assign) NSString *gemeente;
#property (nonatomic, copy) NSString *straat;
#property (nonatomic, assign) int deelnemers;
#property (nonatomic, copy) NSDate *start;
#property (nonatomic, copy) NSDate *einde;
#property (nonatomic, copy) NSString *plaats;
#property (nonatomic, readonly) int id_nr;
#property (nonatomic, assign) int huisnummer;
#end
event.m
#import "Event.h"
#implementation Event
#synthesize coordinate, title, zone, gemeente, straat, deelnemers, start, einde, plaats, id_nr, huisnummer, description;
#end
Important to note, maybe, is that ARC is on.
Have you tried changing the coordinate property to readwrite? (assign would be a good choice.)

iPhone Super/SubClass Example

I have a superclass Question:
import <Foundation/Foundation.h>
#import "Answer.h"
#interface Question : NSObject {
NSString* qId;
NSString* qTitle;
NSString* qNumber;
NSString* sectionId;
NSString* type;
Answer* answer;
}
#property (nonatomic, retain) NSString* qId;
#property (nonatomic, retain) NSString* qTitle;
#property (nonatomic, retain) NSString* qNumber;
#property (nonatomic, retain) NSString* sectionId;
#property (nonatomic, retain) NSString* type;
#property (nonatomic, retain) Answer* answer;
#end
#import "Question.h"
#implementation Question
#synthesize qId, qTitle, qNumber, sectionId, type, answer;
-(id)init
{
if (self = [super init])
{
// Initialization code here
answer = [[Answer alloc]init];
}
return self;
}
-(void) dealloc{
[answer release];
[super dealloc];
}
#end
I have several types of Question, one example is a Slider Question. I want this class to subclass Question:
#import <Foundation/Foundation.h>
#import "Question.h"
#interface SliderQuestion : Question {
(NSString*) min;
(NSString*) max;
}
#property (nonatomic, retain) NSString* min;
#property (nonatomic, retain) NSString* max;
#end
}
#import "SliderQuestion.h"
#implementation SliderQuestion
#synthesize min, max;
#end
Is this the correct way to subclass? Will SliderQuestion inherit the properties contained within Question?
SliderQuestion* s = [[SliderQuestion alloc]init];
NSLog(#"%#", s.qId); //is this valid
Do you really want min and max to be instances of NSString? It seems that floats would be more appropriate.
Also, scrap the () in (NSString *) to remove the warning/error message.
Finally, this is the appropriate way to subclass. An instance of SliderQuestion will inherit all properties and methods of the Question class (and NSObject as well)
Notice the ( and ) around the NSStrings, you might wanna remove those.