Magical Data Modeling Framework for JSON - allows rapid creation of smart data models. You can use it in your iOS, macOS, watchOS and tvOS apps.

Related tags

JSON jsonmodel
Overview

JSONModel - Magical Data Modeling Framework for JSON

JSONModel allows rapid creation of smart data models. You can use it in your iOS, macOS, watchOS and tvOS apps. Automatic introspection of your model classes and JSON input drastically reduces the amount of code you have to write.

See CHANGELOG.md for details on changes.

Installation

CocoaPods

pod 'JSONModel'

Carthage

github "jsonmodel/jsonmodel"

Manual

  1. download the JSONModel repository
  2. copy the JSONModel sub-folder into your Xcode project
  3. link your app to SystemConfiguration.framework

Basic Usage

Consider you have JSON like this:

{ "id": 10, "country": "Germany", "dialCode": 49, "isInEurope": true }
  • create a JSONModel subclass for your data model
  • declare properties in your header file with the name of the JSON keys:
@interface CountryModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *country;
@property (nonatomic) NSString *dialCode;
@property (nonatomic) BOOL isInEurope;
@end

There's no need to do anything in the implementation (.m) file.

  • initialize your model with data:
NSError *error;
CountryModel *country = [[CountryModel alloc] initWithString:myJson error:&error];

If the validation of the JSON passes. you have all the corresponding properties in your model populated from the JSON. JSONModel will also try to convert as much data to the types you expect. In the example above it will:

  • convert id from string (in the JSON) to an int for your class
  • copy the country value
  • convert dialCode from a number (in the JSON) to an NSString value
  • copy the isInEurope value

All you have to do is define the properties and their expected types.

Examples

Automatic name based mapping

{
	"id": 123,
	"name": "Product name",
	"price": 12.95
}
@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@end

Model cascading (models including other models)

{
	"orderId": 104,
	"totalPrice": 13.45,
	"product": {
		"id": 123,
		"name": "Product name",
		"price": 12.95
	}
}
@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@end

@interface OrderModel : JSONModel
@property (nonatomic) NSInteger orderId;
@property (nonatomic) float totalPrice;
@property (nonatomic) ProductModel *product;
@end

Model collections

{
	"orderId": 104,
	"totalPrice": 103.45,
	"products": [
		{
			"id": 123,
			"name": "Product #1",
			"price": 12.95
		},
		{
			"id": 137,
			"name": "Product #2",
			"price": 82.95
		}
	]
}
@protocol ProductModel;

@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@end

@interface OrderModel : JSONModel
@property (nonatomic) NSInteger orderId;
@property (nonatomic) float totalPrice;
@property (nonatomic) NSArray <ProductModel> *products;
@end

Note: the angle brackets after NSArray contain a protocol. This is not the same as the Objective-C generics system. They are not mutually exclusive, but for JSONModel to work, the protocol must be in place.

Also property can have generics info for compiler

@interface OrderModel : JSONModel
@property (nonatomic) NSInteger orderId;
@property (nonatomic) float totalPrice;
@property (nonatomic) NSArray<ProductModel *> <ProductModel> *products;
@end

Nested key mapping

{
	"orderId": 104,
	"orderDetails": {
		"name": "Product #1",
		"price": {
			"usd": 12.95
		}
	}
}
@interface OrderModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *productName;
@property (nonatomic) float price;
@end

@implementation OrderModel

+ (JSONKeyMapper *)keyMapper
{
	return [[JSONKeyMapper alloc] initWithModelToJSONDictionary:@{
		@"id": @"orderId",
		@"productName": @"orderDetails.name",
		@"price": @"orderDetails.price.usd"
	}];
}

@end

Map automatically to snake_case

{
	"order_id": 104,
	"order_product": "Product #1",
	"order_price": 12.95
}
@interface OrderModel : JSONModel
@property (nonatomic) NSInteger orderId;
@property (nonatomic) NSString *orderProduct;
@property (nonatomic) float orderPrice;
@end

@implementation OrderModel

+ (JSONKeyMapper *)keyMapper
{
	return [JSONKeyMapper mapperForSnakeCase];
}

@end

Optional properties (i.e. can be missing or null)

{
	"id": 123,
	"name": null,
	"price": 12.95
}
@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString <Optional> *name;
@property (nonatomic) float price;
@property (nonatomic) NSNumber <Optional> *uuid;
@end

Ignored properties (i.e. JSONModel completely ignores them)

{
	"id": 123,
	"name": null
}
@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString <Ignore> *customProperty;
@end

Making scalar types optional

{
	"id": null
}
@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@end

@implementation ProductModel

+ (BOOL)propertyIsOptional:(NSString *)propertyName
{
	if ([propertyName isEqualToString:@"id"])
		return YES;

	return NO;
}

@end

Export model to NSDictionary or JSON

ProductModel *pm = [ProductModel new];
pm.name = @"Some Name";

// convert to dictionary
NSDictionary *dict = [pm toDictionary];

// convert to json
NSString *string = [pm toJSONString];

Custom data transformers

@interface JSONValueTransformer (CustomTransformer)
@end

@implementation JSONValueTransformer (CustomTransformer)

- (NSDate *)NSDateFromNSString:(NSString *)string
{
	NSDateFormatter *formatter = [NSDateFormatter new];
	formatter.dateFormat = APIDateFormat;
	return [formatter dateFromString:string];
}

- (NSString *)JSONObjectFromNSDate:(NSDate *)date
{
	NSDateFormatter *formatter = [NSDateFormatter new];
	formatter.dateFormat = APIDateFormat;
	return [formatter stringFromDate:date];
}

@end

Custom getters/setters

@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@property (nonatomic) NSLocale *locale;
@end

@implementation ProductModel

- (void)setLocaleWithNSString:(NSString *)string
{
	self.locale = [NSLocale localeWithLocaleIdentifier:string];
}

- (void)setLocaleWithNSDictionary:(NSDictionary *)dictionary
{
	self.locale = [NSLocale localeWithLocaleIdentifier:dictionary[@"identifier"]];
}

- (NSString *)JSONObjectForLocale
{
	return self.locale.localeIdentifier;
}

@end

Custom JSON validation

@interface ProductModel : JSONModel
@property (nonatomic) NSInteger id;
@property (nonatomic) NSString *name;
@property (nonatomic) float price;
@property (nonatomic) NSLocale *locale;
@property (nonatomic) NSNumber <Ignore> *minNameLength;
@end

@implementation ProductModel

- (BOOL)validate:(NSError **)error
{
	if (![super validate:error])
		return NO;

	if (self.name.length < self.minNameLength.integerValue)
	{
		*error = [NSError errorWithDomain:@"me.mycompany.com" code:1 userInfo:nil];
		return NO;
	}

	return YES;
}

@end

License

MIT licensed - see LICENSE file.

Contributing

We love pull requests! See CONTRIBUTING.md for full details.

Comments
  • Crashes in JSONModel.m line 855 (reason unknown)

    Crashes in JSONModel.m line 855 (reason unknown)

    Since using JSONModel 1.2.0 our app is regularly reporting crashes in JSONModel dictionary deserialization. To be specific, the crashes happen in __customSetValue:forProperty:.

    Sadly, I cannot provide any data that reproduces the error, but maybe the author can find any possible problem in this code.

    Here is the respective call stack of one such crash:

    Thread : Crashed: com.apple.root.default-qos
    0  libobjc.A.dylib                0x3958df62 objc_msgSend + 1
    1  CoreFoundation                 0x2b00a17d -[__NSDictionaryM setObject:forKey:] + 340
    2  App                            0x2a316b __arclite_NSMutableDictionary__setObject_forKeyedSubscript(NSMutableDictionary*, objc_selector*, objc_object*, objc_object*) (arclite.mm:1669)
    3  App                            0x1d2bed -[JSONModel __customSetValue:forProperty:] (JSONModel.m:855)
    4  App                            0x1d0b7b -[JSONModel __importDictionary:withKeyMapper:validation:error:] (JSONModel.m:342)
    5  App                            0x1cfbd9 -[JSONModel initWithDictionary:error:] (JSONModel.m:191)
    6  App                            0x1d3a15 +[JSONModel arrayOfModelsFromDictionaries:error:] (JSONModel.m:1124)
    7  App                            0x1bb4dd __68-[AppService service:success:failure:]_block_invoke_2 (AppService.m:21)
    8  libdispatch.dylib              0x39b11c83 _dispatch_call_block_and_release + 10
    9  libdispatch.dylib              0x39b1e86b _dispatch_root_queue_drain + 1374
    10 libdispatch.dylib              0x39b1f8a3 _dispatch_worker_thread3 + 106
    11 libsystem_pthread.dylib        0x39c93d9d _pthread_wqthread + 668
    12 libsystem_pthread.dylib        0x39c93af0 start_wqthread + 8
    
    opened by wberger 31
  • Added millisecond support for NSDate objects

    Added millisecond support for NSDate objects

    JSONModel was failing to parse NSDate values with milliseconds, for example "2013-11-27T05:00:00.000Z". I created a fork of JSONModel and made a fix, including an additional unit test case. Could you please review it and pull it into the main project if it looks good?

    Thanks, Scott

    opened by scottadav 24
  • BOOL properties serialize to integers

    BOOL properties serialize to integers

    Hi. Because KVC converts BOOL properties to __NSCFNumber rather than __NSCFBoolean (when using valueForKey:, for example), setting a BOOL property with initWithDictionary results in it being rendered as 0 or 1 rather than 'true' or 'false' when I subsequently serialize my model class to JSON.

    Do you have any suggestions for how to work around this problem? I can't believe I'm the first person to use JSON booleans but I couldn't find any other issue related to this use case.

    Thanks for your help, and for writing JSONModel, which is otherwise great!

    opened by ablock 22
  • Allow collection model subclasses to be defined without using protocols

    Allow collection model subclasses to be defined without using protocols

    An error is thrown after trying to deserialize a typed array in Swift. The type of the array also inherits from JSONModel but the deserialization does not dive into the dictionaries inside the array. So instead of giving an array with objects of JSONModelSubClass it gives an array of NSDictionary objects.

    The error: "fatal error: NSArray element failed to match the Swift Array Element type"

    So, I fixed that by giving an option to supply a dictionary with array names and their types. Like JSONKeyMapper is initialized with custom mapping dictionary, I gave the option to implement a method for declaring arrays and types mapping.

    I'll upload my fix to this issue's branch and you guys can review it.

    Thanks!

    opened by PerrchicK 18
  • JSONModel copy

    JSONModel copy

    I have a subclass of JSONModel.

    Let's call the subclass MyModel.

    MyModel *a = ....

    [a copy] performs only a shallow copy. Is this intended behaviour? How can I get it to do a deep copy so the NSDate * fields's values get copied over.

    opened by pjebs 17
  • about dictionary value is array

    about dictionary value is array

    @billinghamj i need help, thanks

    
    {
        "response": {
            "49": {
                "count": 6,
                "list": {
                    "16:50-17:50": [
                        {
                            "first_address": "B",
                            "order_id": "458260",
                            "order_num": 10,
                            "time": "16:50-17:50",
                            "user_id": "71851"
                        },
                        {
                            "first_address": "B",
                            "order_id": "458261",
                            "order_num": 11,
                            "time": "16:50-17:50",
                            "user_id": "71851"
                        },
                        {
                            "first_address": "B",
                            "order_id": "458262",
                            "order_num": 12,
                            "time": "16:50-17:50",
                            "user_id": "71851"
                        }
                    ],
                    "18:10-19:00": [
                        {
                            "first_address": "B",
                            "order_id": "458263",
                            "order_num": 13,
                            "time": "18:10-19:00",
                            "user_id": "71851"
                        },
                        {
                            "first_address": "B",
                            "order_id": "458264",
                            "order_num": 14,
                            "time": "18:10-19:00",
                            "user_id": "71851"
                        },
                        {
                            "first_address": "B",
                            "order_id": "458265",
                            "order_num": 15,
                            "time": "18:10-19:00",
                            "user_id": "71851"
                        }
                    ]
                },
                "name": "food"
            }
        },
        "responseTime": "1453710085",
        "result": "true",
        "resultElapse": 6,
        "resultMessage": "success",
        "resultNum": "200"
    }
    
    
    
    @interface Response : JSONModel
    @property (assign, nonatomic)BOOL result;
    @property (assign, nonatomic)NSInteger resultNum;
    @property (assign, nonatomic)NSInteger responseTime;
    @property (strong, nonatomic)NSString *resultMessage;
    @property (strong, nonatomic)NSDictionary <GroupOrder> *response;
    @end
    
    
    @protocol GroupOrder
    @end
    @interface GroupOrder : JSONModel
    @property (strong, nonatomic) NSDictionary<NSString*, NSArray<Order>*> *list;
    @property (strong, nonatomic) NSString *name;
    @property (nonatomic) int count;
    
    @end
    
    @protocol Order
    @end
    
    @interface Order : JSONModel
    @property (strong, nonatomic) NSString *first_address;
    @property (nonatomic) int order_id;
    @property (nonatomic) int order_num;
    @property (strong, nonatomic) NSString *time;
    @property (nonatomic) int *user_id;
    
    @end
    

    how should I declare GroupOrder property list?

    opened by a0000 16
  • New Objective C syntax (lightweight generics)

    New Objective C syntax (lightweight generics)

    In the new version of Objective C (on XCode 7), we can now specify what a NSArray can contain.

    Will your library support this? It will definitely reduce the amount of casting we need to do.

    Say we have a JSONModel subclass called Cars.

    Say we have another JSONModel subclass called Person:

    @property (strong, nonatomic) NSArray < Cars * > * cars; //Restricting NSArray to Cars

    rather than currently:

    @protocol Cars @end

    @property (strong, nonatomic) NSArray < Cars > * cars; //Currently

    opened by pjebs 16
  • Status Codes

    Status Codes

    Is there a way to handle different status codes back from an API. For instance, if the server returns a 401 for an expired/reset authentication token, or a 500 or server outage there is no way to tell the difference. Would it be possible to simply pass the error code up along with the JSONModelError?

    opened by azuby 16
  • Core Data

    Core Data

    Hello,

    Is there some way to use JSONModel do create Core Data objects? The only way I can think is to let JSONModel handle all the JSON work and then copy all the fields to a custom NSManagedObject if the conversion was successful… or is there another way to create the NSManagedObject that I'm not aware of?

    Thanks!

    opened by carlosefonseca 16
  • Fix custom setter dictionary crash when multithreading(#436)

    Fix custom setter dictionary crash when multithreading(#436)

    Fix crash by moving custom setter name generation to __inspectProperties__ method. @billinghamj Do you have unit test cases I can run with? to check the fix won't break other parts.

    opened by robinzhangx 15
  • [Release] v1.2.0

    [Release] v1.2.0

    With quite a number of changes being made recently to the library, we need to prep for a new release.

    A number of changes have been made which are not breaking, but do slightly change behavior in minor ways. As such, I think it'd make more sense to bump the minor number, rather than the patch - to indicate that the change is a little more significant.

    I think it's probably worth trying to close a few more PRs and issues before cutting this release, but it's here for the discussion now.

    @icanzilb - we'll need a bit of help from you to agree the details of the release and then push to Cocoapods, if you have a little time for this?

    opened by billinghamj 15
  • Added Swift package manager support to JSONModel

    Added Swift package manager support to JSONModel

    Would it be possible to get this in and a new release from the master after that?

    I know that this repo is bit stale, but this is still used in some projects and it would be nice that we could point to release and the original code base.

    opened by MapaX 2
  • UIColor ?

    UIColor ?

    If i try to use UIColor property i get: [JSONValueTransformer __JSONObjectFromUIColor:] not found

    In the debug i see "value" is "UIExtendedSRGBColorSpace 0 1 0 1"

    Should i write some additional text to support UIColor ?

    opened by SmartHbdev 0
  • How to convert JSONModel class properties to snake_case NSDictionary?

    How to convert JSONModel class properties to snake_case NSDictionary?

    Hello, I am new to this library and after searching through the issues and through the code I did not find any solution to this question. I am using [JSONKeyMapper mapperForSnakeCase] to map dictionary keys to the class properties and was wondering if there is a method where I can convert the class properties back to snake_case dictionary to send the data with the same keys the server sent initially before mapping in snake_case. Thank you!

    opened by CochiorasBogdan 0
Releases(1.7.0)
  • 1.7.0(Oct 7, 2016)

  • 1.6.0(Oct 5, 2016)

  • 1.5.1(Sep 12, 2016)

  • 1.5.0(Sep 12, 2016)

    • deprecated mapperFromUpperCaseToLowerCase (not replaced - it didn't really make sense)
    • renamed mapperFromUnderscoreCaseToCamelCase to mapperForSnakeCase for clarity
    Source code(tar.gz)
    Source code(zip)
  • 1.4.2(Sep 12, 2016)

  • 1.4.1(Sep 12, 2016)

  • 1.4.0(Sep 12, 2016)

  • 1.3.0(Jul 22, 2016)

    Sorry for the long time since the last release. We'll be trying to maintain a more rapid release schedule going forwards.

    • precision issue fixed with deserializing numbers
    • support added for deserializing into a 'root' dictionary (dictionaryOfModelsFromDictionary:error:, etc.)
    • lazy collection-type conversion (ConvertOnDemand) is no longer supported
    • deprecated two way key mapping deprecated - only Model->JSON has ever worked anyway
    • deprecated all networking support
    • deprecated the global key mapper
    • deprecated Index protocol
    • deprecated protocolForArrayProperty: in favor of classForCollectionProperty:
    • modulemap file added to handle use as a framework better
    • success return value added to mergeFromDictionary:useKeyMapping:error:
    • JSONModel has now been moved out into its own GitHub organization, etc. - now maintained by multiple people

    Potential Breaking Changes

    • new behavior for handling null values when serializing:
      • values of NSNull will now always null in JSON output
      • values of nil will now never be included in JSON output
    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Jul 22, 2016)

    • support added for watchOS and tvOS
    • minimum iOS version bumped to 6.0
    • support added for Carthage
    • deprecated +arrayOfModelsFromDictionaries: in favor of +arrayOfModelsFromDictionaries:error:
    • added +arrayOfModelsFromString:error:
    • deprecated +mergeFromDictionary: in favor of mergeFromDictionary:useKeyMapping:error:
    • added support for multiple custom setters
    • fixed -hash implementation
    • added responseData property to JSONModelError
    • added support for creating a key mapper with exceptions (+mapper:withExceptions:)
    • locks now used in key mapper implementation for additional safety
    • fixed behavior of NSURLFromNSString transformer
    • updated project files to latest Xcode
    • updated demo apps to work with the latest JSONModel & external API code
    Source code(tar.gz)
    Source code(zip)
Owner
JSONModel
JSONModel
Flexible JSON traversal for rapid prototyping

RBBJSON RBBJSON enables flexible JSON traversal at runtime and JSONPath-like que

Robb Böhnke 164 Dec 27, 2022
Argo is a library that lets you extract models from JSON or similar structures in a way that's concise, type-safe, and easy to extend

Argo is a library that lets you extract models from JSON or similar structures in a way that's concise, type-safe, and easy to extend. Using Argo

thoughtbot, inc. 3.5k Dec 20, 2022
macOS app to generate Swift 5 code for models from JSON (with Codeable)

SwiftyJSONAccelerator - MacOS app Codeable Model file Generator For Swift 5 Version v2.2 Generate initializer function for classes Application Downloa

Karthikeya Udupa 929 Dec 6, 2022
An iOS framework for creating JSON-based models. Written in Swift.

An iOS framework for creating JSON-based models. Written in Swift (because it totally rules!) Requirements iOS 8.0+ Xcode 7.3 Swift 2.2 Installation E

Oven Bits 448 Nov 8, 2022
JSONHelper - ✌ Convert anything into anything in one operation; JSON data into class instances, hex strings into UIColor/NSColor, y/n strings to booleans, arrays and dictionaries of these; anything you can make sense of!

JSONHelper Convert anything into anything in one operation; hex strings into UIColor/NSColor, JSON strings into class instances, y/n strings to boolea

Baris Sencan 788 Jul 19, 2022
A fast, convenient and nonintrusive conversion framework between JSON and model. Your model class doesn't need to extend any base class. You don't need to modify any model file.

MJExtension A fast, convenient and nonintrusive conversion framework between JSON and model. 转换速度快、使用简单方便的字典转模型框架 ?? ✍??Release Notes: more details Co

M了个J 8.5k Jan 3, 2023
Codable code is a Swift Package that allows you to convert JSON Strings into Swift structs

Codable code is a Swift Package that allows you to convert JSON Strings into Swift structs.

Julio Cesar Guzman Villanueva 2 Oct 6, 2022
ObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects to and from JSON.

ObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects (classes and structs) to and from J

Tristan Himmelman 9k Jan 2, 2023
Swift parser for JSON Feed — a new format similar to RSS and Atom but in JSON.

JSONFeed Swift parser for JSON Feed — a new format similar to RSS and Atom but in JSON. For more information about this new feed format visit: https:/

Toto Tvalavadze 31 Nov 22, 2021
JSONNeverDie - Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die

JSONNeverDie is an auto reflection tool from JSON to Model, a user friendly JSON encoder / decoder, aims to never die. Also JSONNeverDie is a very important part of Pitaya.

John Lui 454 Oct 30, 2022
JSEN (JSON Swift Enum Notation) is a lightweight enum representation of a JSON, written in Swift.

JSEN /ˈdʒeɪsən/ JAY-sən JSEN (JSON Swift Enum Notation) is a lightweight enum representation of a JSON, written in Swift. A JSON, as defined in the EC

Roger Oba 8 Nov 22, 2022
JSON-Practice - JSON Practice With Swift

JSON Practice Vista creada con: Programmatic + AutoLayout Breve explicación de l

Vanesa Giselle Korbenfeld 0 Oct 29, 2021
Ss-json - High-performance json parsing in swift

json 0.1.1 swift-json is a pure-Swift JSON parsing library designed for high-per

kelvin 43 Dec 15, 2022
Swift-json - High-performance json parsing in swift

json 0.1.4 swift-json is a pure-Swift JSON parsing library designed for high-per

kelvin 43 Dec 15, 2022
Developed with use Swift language. As a third party library used SDWebImage. JSON parsing using URLSession with TMDB API. This app provide by the Core Data structure.

Capstone Project ?? About Developed with use Swift language. As a third party library used SDWebImage. JSON parsing using URLSession with TMDB API. Ad

Ensar Batuhan Unverdi 9 Aug 22, 2022
JSONExport is a desktop application for Mac OS X which enables you to export JSON objects as model classes with their associated constructors, utility methods, setters and getters in your favorite language.

JSONExport JSONExport is a desktop application for Mac OS X written in Swift. Using JSONExport you will be able to: Convert any valid JSON object to a

Ahmed Ali 4.7k Dec 30, 2022
Application where you can build your portfolio with your Educations, Experiences, Projects, and Achievements

App Store Link Application where you can build your portfolio with your Educations, Experiences, Projects, and Achievements Description Signup with ne

Marwan Sultan 19 Jun 23, 2022
Library of Swiftui Views conforming to Codable, meaning we can produce JSON driven UI!

CodableView Library of Swiftui Views conforming to Codable, meaning we can produce JSON driven UI! Adding a CodableView Type Create View that conforms

Daniel Bolella 3 Apr 2, 2022
JOP is the Json organization program. It can run on any platform that supports Swift.

JOP JOP is a program organized in JSON files. It is based on Swift, provides a syntax similar to Swift, and has the same strong security as Swift. Thi

Underthestars-zhy 1 Nov 18, 2021