JSONModel library / model collection wrong - ios

I'm using JSONMODEl (https://github.com/icanzilb/JSONModel) to parse a wordpress JSON FEED (with json-api).
Everything go's well except if I want the "comments".
my feed is like that :
comments = (
{
content = "<p>My comment</p>\n";
date = "2014-08-29 20:56:29";
id = 97813;
name = johndoe;
parent = 0;
url = "http://www.google.com";
}
);
so I try to make my "newsmodel" like that :
#import "JSONModel.h"
#import "commentmodel.h"
#protocol NewsModel #end
#interface NewsModel : JSONModel
#property (strong, nonatomic) NSString* title;
#property (strong, nonatomic) NSString* content;
#property (strong, nonatomic) NSString* thumbnail_images;
#property (strong, nonatomic) NSString* premium;
#property (strong, nonatomic) NSString* id;
#property (strong, nonatomic) CommentModel* comments;
#end
and my commentmodel like that
#import "JSONModel.h"
#interface CommentModel : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* name;
#property (assign, nonatomic) NSString* content;
#end
But When I try to build my app, my "feed" is empty.
if I comment the "comment" part of the news model, I got the content....
I think I'm stuck somewhere, but where ! If someone ave an idea :)
Many thanks

comments is an array, not a single comment, notice the top level ( and ) which designate an array in a NSDictionary NSLog(). Inside of the is an array element designated by { and }.
But the NewsModel has comments defined as a single comment (CommentModel), not an array. it should probably be declared:
In the docs see Model collections and how products is handled.
You will have to declare a protocol, see the example protocol at the top of the "Model collections" examples.
#protocol CommentModel
#end
Above:
#interface CommentModel : JSONModel
#property (strong, nonatomic) NSArray< CommentModel >* comments;

#protocol CommentModel
#end
#interface CommentModel : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* name;
#property (assign, nonatomic) NSString* content;
#end
#interface NewsModel : JSONModel
#property (strong, nonatomic) NSString* title;
#property (strong, nonatomic) NSString* content;
#property (strong, nonatomic) NSString* thumbnail_images;
#property (strong, nonatomic) NSString* premium;
#property (strong, nonatomic) NSString* id; //int?
#property (strong, nonatomic) NSArray<CommentModel>* comments;
#end

Thanks, got it to build, but now If i try to alloc it with
#try {
_feed = [[NewsFeed alloc] initWithDictionary:obj error:nil];
}
#catch (NSException *e) {
NSLog(#"Parse error : %# reason %#", [e name], [e reason]);
}
I got a Bad property protocol declaration reason is not allowed JSONModel property protocol, and not a JSONModel class.
my news feed is like that
#interface NewsFeed : JSONModel
#property (nonatomic, strong) NSArray <NewsModel> *posts;
#end
And work like a charme without the "comment" part...
Thanks

As an addition to the answers above, since I can't add a comment yet, all you have to do, is add an empty protocol with the same name, like this:
#protocol CommentModel
#end
Then, as noted here JsonModel documentation, notation would be different than a notation. The first one is a protocol declaration needed for JsonModel to work, the other one is an objc compiler helper declaration. You can combine them as noted in the same example:
#property (nonatomic) NSArray<ProductModel *> <ProductModel> *products;

Related

jsonmodel - Model cascading (models including other models)

I'm using the same example on the web
OrderModel.h
#protocol ProductModel
#end
#interface ProductModel : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* name;
#property (assign, nonatomic) float price;
#end
#implementation ProductModel
#end
#interface OrderModel : JSONModel
#property (assign, nonatomic) int order_id;
#property (assign, nonatomic) float total_price;
#property (strong, nonatomic) NSArray<ProductModel>* products;
#end
#implementation OrderModel
#end
But when I build the project I face one issue "Duplicate symbols"
duplicate symbol _OBJC_CLASS_$_OrderModel
ld: 576 duplicate symbols for architecture arm64
clang: error: linker command failed with exit code 1
The #implementation should be present in a .m file and the #interface in a .h file.
You should only import the .h file. Otherwise you will have multiple implementations for the same class.
ProductModel.h:
#interface ProductModel : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* name;
#property (assign, nonatomic) float price;
#end
ProductModel.m:
#import "ProductModel.h"
#implementation ProductModel
#end
OrderModel.h:
#interface OrderModel : JSONModel
#property (assign, nonatomic) int order_id;
#property (assign, nonatomic) float total_price;
#property (strong, nonatomic) NSArray<ProductModel>* products;
#end
OrderModel.m
#import "OrderModel.h"
#implementation OrderModel
#end
If you would want to use the ProductModel class in a View Controller for example just import the "ProductModel.h":
#import "ProductModel.h"

Converting jsonarray (having different type) to model array using JSONModel Library

I have one problem in converting JSON array to model. I am using JSONModel library.
#protocol PTTemplateModel <NSObject>
#end
#protocol PTProfileTemplateModel <PTTemplateModel>
#end
#protocol PTCategoryTemplateModel <PTTemplateModel>
#end
#interface PTTemplateModel : JSONModel
#property (nonatomic, assign) TemplateType type;
#property (nonatomic, copy) NSString* templateID;
#end
#interface PTProfileTemplateModel : PTTemplateModel
#property (nonatomic, copy) NSString* logoURL;
#property (nonatomic, copy) NSString* title;
#end
#interface PTCategoryTemplateModel : PTTemplateModel
#property (nonatomic, strong) NSString* category;
#end
#interface PTModel : JSONModel
#property (nonatomic, copy) NSString* title;
#property (nonatomic, strong) NSArray< PTTemplateModel>* templates; // PTTemplateModel
Here templates array can have both PTProfileTemplateModel and PTCategoryTemplateModel.
JSON Input:
{"title":"Core","templates":[{"type":0,"templateID":"","logoURL":"", "title":"data"},{"type":1,"templateID":"","category":"DB"}]}
What I need is according to type I have to get CategoryTemplate or ProfileTemplate. But after conversion I am getting just PTTemplateModel type.
I know that I have specified protocol type as PTTemplateModel. But how do I get different type of model according to given data.
I tried:
#property (nonatomic, strong) NSArray< PTTemplateModel>* templates;
#property (nonatomic, strong) NSArray<PTProfileTemplateModel, PTCategoryTemplateModel>* templates;
#property (nonatomic, strong) NSArray< PTTemplateModel , PTProfileTemplateModel, PTCategoryTemplateModel>* templates;
None of them works.
Any suggestions?
Why not try BWJSONMatcher, it helps you work with json data in a very very neat way:
#interface PTModel : NSObject<BWJSONValueObject>
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSArray *templates;
#end
#interface PTTemplateModel : NSObject
#property (nonatomic, assign) TemplateType type;
#property (nonatomic, strong) NSString *templateID;
#property (nonatomic, strong) NSString *logoURL;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *category;
#end
In the implementation of PTModel, implement the function typeInProperty: declared in protocol BWJSONValueObject:
- (Class)typeInProperty:(NSString *)property {
if ([property isEqualToString:#"templates"]) {
return [PTTemplateModel class];
}
return nil;
}
Then you can use BWJSONMatcher to get your data model within one line:
PTModel *model = [PTModel fromJSONString:jsonString];
Detailed examples of how to use BWJSONMatcher can be found here.

How do I set another ViewController's property without using a segue?

From my MCSettingsFormViewController, I want to set MatchCenterViewController's didAddNewItem BOOL property, but without making use of a segue.
I've imported MatchCenterViewController.h, which contains that property like so:
#property (assign) BOOL didAddNewItem;
However, when I try to set it like this: MatchCenterViewController.didAddNewItem = YES;, it says "property didAddNewItem not found on object of type 'MatchCenterViewController'".
I assume this is because I haven't defined what MatchCenterViewController is. If so, how can I do this property so it sets the property correctly?
edit:
MatchCenterViewController.h:
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import "AsyncImageView.h"
#import "SearchViewController.h"
#import "WebViewController.h"
#import "WSCoachMarksView.h"
#import "SLExpandableTableView.h"
#interface MatchCenterViewController : UIViewController <UITableViewDataSource>
#property (strong, nonatomic) NSString *itemSearch;
#property (strong, nonatomic) NSString *itemPriority;
//#property (strong, nonatomic) IBOutlet UITextField *itemSearch;
#property (nonatomic, strong) NSArray *imageURLs;
#property (strong, nonatomic) NSString *matchingCategoryCondition;
#property (strong, nonatomic) NSString *matchingCategoryLocation;
#property (strong, nonatomic) NSNumber *matchingCategoryMaxPrice;
#property (strong, nonatomic) NSNumber *matchingCategoryMinPrice;
#property (strong, nonatomic) NSNumber *matchingCategoryId;
#property (strong, nonatomic) NSArray *matchCenterArray;
#property (strong, nonatomic) NSString *searchTerm;
#property (strong, nonatomic) NSString *itemURL;
#property (assign) NSInteger expandedSection;
#property (assign) NSInteger rowCount;
#property (assign) BOOL didAddNewItem;
#property (assign) BOOL results;
#property (strong, nonatomic) IBOutlet UIButton *editButton;
#property (weak, nonatomic) IBOutlet UIButton *moreButton;
#property (strong) NSMutableSet *expandedSections;
#end
#interface MoreButton : UIButton
#property (assign) NSInteger expandedSection;
#property (assign) NSInteger sectionIndex;
#end
MCSettingsFormViewController.h:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <Parse/Parse.h>
#import "MatchCenterViewController.h"
#interface MCSettingsFormViewController : UIViewController
#property (strong, nonatomic) NSString *minPrice;
#property (strong, nonatomic) NSString *maxPrice;
#property (strong, nonatomic) NSString *itemCondition;
#property (strong, nonatomic) NSString *itemLocation;
#property (strong, nonatomic) NSString *searchTerm;
#property (strong, nonatomic) NSString *itemPriority;
#property (strong, nonatomic) IBOutlet UITextField *tf;
#property (strong, nonatomic) IBOutlet UITextField *tf1;
#property (strong, nonatomic) IBOutlet UITextField *tf2;
#end
You need to use an instance of MatchCenterViewController not the name of the class. Presumably, somewhere in your app there's a reference to a MatchCenterViewController object. You can either access that reference or pick a different way of letting it know about the change.
For example, if your two controllers aren't connected to each other, you could post a notification in MCSettingsFormViewController and react to it in MatchCenterViewController.
For more specific suggestions, I'd need to know how both controllers are created and presented.
When you instantiate MatchCenterViewController, you could set it as a delegate of MCSettingsFormViewController. That way, the MatchCenterViewController defines itself as the instantiated version of the class to be edited by the MatchCenterViewController.
Here is a basic tutorial for delegates: http://www.tutorialspoint.com/ios/ios_delegates.htm
So based off of your headers, it looks like either your MCSettingsFormViewController doesn't have a property of type MatchCenterViewController-- or that property is private.
In the former case, you need to add a property to your MCSettingsFormViewController with type MatchCenterViewController.
In the latter you aren't initializing your MatchCenterViewController property.
So first, make sure you have that public/private property.
Then, when you first create and show your SettingsFormViewController, set this property to your MatchCenterViewController instance. Now your SettingsForm has a reference to the proper instance you're looking for.
At this point, you can set the property on the MatchCenter

JSONModel with data from several JSON sources

I have a fairly basic problem with the JSONModel. Let's say I have the following JSON:
{"items": [
{
"id": 1,
"title": "Bla",
"category": 1
}
]}
and this one:
{"categories": [
{
"id": 1,
"name": "Category"
}
]}
Now the easiest thing would be to put the categories inside the items and have JSONModel just use that. But there might be hundreds of items which share just a few categories, and the categories have several attributes like description, URLs and stuff, and that would blow up the items JSON.
How would I combine them in the best way using JSONModel (or might another library be better)?
My models currently look like this:
#interface Item : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* title;
#property (strong, nonatomic) Category* category;
#end
#interface Category : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* name;
#end
try this
#protocol Item
#end
#interface Item : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* title;
#property (strong, nonatomic) Category* category;
#end
#interface Items : JSONModel
#property (strong, nonatomic) NSArray<Item> *items;
#end
#protocol Category
#end
#interface Category : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString *name;
#end
#interface Categories : JSONModel
#property (strong, nonatomic) NSArray<Category> *categories;
#end
Your JSON is array of items or categories

JSONModel Invalid JSON data

I have this Json out of ASP MVC API
I have the InvModel and the LotModel
but when I call
_InvFeed = [[InvModel alloc] initFromURLWithString:#"http://192.168.1.206/service/api/dto/inventory/1?p=Red%20Globe"
completion:^(JSONModel *model, JSONModelError *err)
{
NSLog(#"Inventory: %#", _InvFeed );
NSLog(#"Error: %#",err);
}];
I can not figure out this error:
Error: Error Domain=JSONModelErrorDomain Code=1 "Invalid JSON data:
Attempt to initialize JSONModel object using initWithDictionary:error:
but the dictionary parameter was not an 'NSDictionary'."
UserInfo=0x109075ff0 {NSLocalizedDescription=Invalid JSON data:
Attempt to initialize JSONModel object using initWithDictionary:error:
but the dictionary parameter was not an 'NSDictionary'.,
kJSONModelKeyPath=LotDTO}
and here are the JSONModels for: LotDTO
#import "JSONModel.h"
#interface InvLotModel : JSONModel
#property (assign, nonatomic) int lotid;
#property (strong, nonatomic) NSDate* expdate;
#property (strong, nonatomic) NSString* lotserial;
#property (strong, nonatomic) NSDate* lastupddate;
#property (strong, nonatomic) NSString<Optional>* providerlotserial;
#property (assign, nonatomic) NSDecimal* qtyoriginal;
#property (assign, nonatomic) NSDecimal* qtyallocated;
#property (assign, nonatomic) NSDecimal* qtyavailable;
#property (assign, nonatomic) NSDecimal* qtyonhand;
#property (strong, nonatomic) NSDate* receiptdate;
#property (strong, nonatomic) NSString* linecomment;
#property (assign, nonatomic) NSDecimal* unitcost;
#property (strong, nonatomic) NSString* warehouse;
#end
And here the Inventory Model
#import "JSONModel.h"
#import "InvLotModel.h"
#protocol InvModel #end
#interface InvModel : JSONModel
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* itemid;
#property (strong, nonatomic) NSString* description;
#property (strong, nonatomic) NSDate* createdate;
#property (strong, nonatomic) NSString* createuser;
#property (assign, nonatomic) float lastcost;
#property (assign, nonatomic) BOOL monitorlevel;
#property (assign, nonatomic) int minlevel;
#property (assign, nonatomic) int maxlevel;
#property (strong, nonatomic) NSString* gtin;
#property (assign, nonatomic) float weight;
#property (strong, nonatomic) NSString* uom;
#property (strong, nonatomic) NSString* sizes;
#property (strong, nonatomic) NSString* variety;
#property (strong, nonatomic) NSString <Optional>* bag;
#property (strong, nonatomic) NSString* style;
#property (strong, nonatomic) NSString* box;
#property (strong, nonatomic) NSString* label;
#property (strong, nonatomic) NSString* commodity;
#property (strong, nonatomic) InvLotModel* LotDTO;
#end
I see two problems:
1) In the InvModel class, yo have defined LotDTO as a single object, not an array.
2) In the JSON response you have posted, the syntax for LotDTO does not seem to me valid JSON. It appears to be an array of LotDTO objects, but it does not follow the syntax for JSON arrays (which you can check, for example, here).
Make sure to mark any extension property as Ignore. I faced such an issue trying to copy the model.
Please replace this
#property (strong, nonatomic) InvLotModel* LotDTO;
with this
#property (strong, nonatomic) NSArray<InvLotModel,ConvertOnDemand>* LotDTO;
As officials at JSONModel suggest to use ConvertOnDemand to convert NSArray to JSONModelArray in one of their tutorial to avoid error in implenentation.
This may help you : Click here

Resources