• Stars
    star
    344
  • Rank 123,066 (Top 3 %)
  • Language
    Objective-C
  • License
    MIT License
  • Created almost 13 years ago
  • Updated about 9 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Auto translates NSDictionary to instances of Objective-C classes, supporting nested types and arrays

Jastor

Jastor is not maintained anymore. No worries, there are some really good alternatives: JSONModel or Mantle

Jastor is an Objective-C base class that is initialized with a dictionary (probably from your JSON response), and assigns dictionary values to all its (derived class's) typed @properties.

It supports nested types, arrays, NSString, NSNumber, NSDate and more.

Jastor is NOT a JSON parser. For that, you have JSONKit, yajl and many others.

The name sounds like JSON to Objecter. Or something.

Upgrade from previous version:

Add dealloc mehtods to your models and nillify your peoperties. Automattic dealloc is no longer done by Jastor.

Support

Need help with getting Jastor up and running? Got a time-consuming problem you want to get solved quickly?
Get Jastor support on CodersClan.

Examples

You have the following JSON:

{
	"name": "Foo",
	"amount": 13
}

and the following class:

@interface Product
@property (nonatomic, copy) NSString *name;
@property (nonatomic, retain) NSNumber *amount;
@end

@implementation Product
@synthesize name, amount;

- (void)dealloc {
	self.name = nil;
	self.amount = nil;
	
	[super dealloc];
}
@end

with Jastor, you can just inherit from Jastor class, and use initWithDictionary:

// Product.h
@interface Product : Jastor
@property (nonatomic, copy) NSString *name;
@property (nonatomic, retain) NSNumber *amount;
@end

// Product.m
@implementation Product
@synthesize name, amount;

- (void)dealloc {
	self.name = nil;
	self.amount = nil;
	
	[super dealloc];
}
@end

// Some other code
NSDictionary *dictionary = /* parse the JSON response to a dictionary */;
Product *product = [[Product alloc] initWithDictionary:dictionary];

// Log
product.name // => Foo
product.amount // => 13

Nested Objects

Jastor also converts nested objects to their destination type:

// JSON
{
	"name": "Foo",
	"category": {
		"name": "Bar Category"
	}
}
// ProductCategory.h
@interface ProductCategory : Jastor
@property (nonatomic, copy) NSString *name;
@end

// ProductCategory.m
@implementation ProductCategory
@synthesize name;

- (void)dealloc {
	self.name = nil;
	
	[super dealloc];
}
@end

// Product.h
@interface Product : Jastor
@property (nonatomic, copy) NSString *name;
@property (nonatomic, retain) ProductCategory *category;
@end

// Product.m
@implementation Product
@synthesize name, category;

- (void)dealloc {
	self.name = nil;
	self.category = nil;
	
	[super dealloc];
}
@end


// Code
NSDictionary *dictionary = /* parse the JSON response to a dictionary */;
Product *product = [[Product alloc] initWithDictionary:dictionary];

// Log
product.name // => Foo
product.category // => <ProductCategory>
product.category.name // => Bar Category

Arrays

Having fun so far?

Jastor also supports arrays of a certain type:

// JSON
{
	"name": "Foo",
	"categories": [
		{ "name": "Bar Category 1" },
		{ "name": "Bar Category 2" },
		{ "name": "Bar Category 3" }
	]
}
// ProductCategory.h
@interface ProductCategory : Jastor
@property (nonatomic, copy) NSString *name;
@end

// ProductCategory.m
@implementation ProductCategory
@synthesize name;

- (void)dealloc {
	self.name = nil;
	
	[super dealloc];
}
@end

// Product.h
@interface Product : Jastor
@property (nonatomic, copy) NSString *name;
@property (nonatomic, retain) NSArray *categories;
@end

// Product.m
@implementation Product
@synthesize name, categories;

+ (Class)categories_class {
	return [ProductCategory class];
}

- (void)dealloc {
	self.name = nil;
	self.categories = nil;
	
	[super dealloc];
}
@end


// Code
NSDictionary *dictionary = /* parse the JSON response to a dictionary */;
Product *product = [[Product alloc] initWithDictionary:dictionary];

// Log
product.name // => Foo
product.categories // => <NSArray>
[product.categories count] // => 3
[product.categories objectAtIndex:1] // => <ProductCategory>
[[product.categories objectAtIndex:1] name] // => Bar Category 2

Notice the declaration of

+ (Class)categories_class {
	return [ProductCategory class];
}

it tells Jastor what class of items the array holds.

Nested + Arrays = Trees

Jastor can handle trees of data:

// JSON
{
	"name": "1",
	"children": [
		{ "name": "1.1" },
		{ "name": "1.2",
		  children: [
			{ "name": "1.2.1",
			  children: [
				{ "name": "1.2.1.1" },
				{ "name": "1.2.1.2" },
			  ]
			},
			{ "name": "1.2.2" },
		  ]
		},
		{ "name": "1.3" }
	]
}
// ProductCategory.h
@interface ProductCategory : Jastor
@property (nonatomic, copy) NSString *name;
@property (nonatomic, retain) NSArray *children;
@end

// ProductCategory.m
@implementation ProductCategory
@synthesize name, children;

+ (Class)children_class {
	return [ProductCategory class];
}

- (void)dealloc {
	self.name = nil;
	self.children = nil;
	
	[super dealloc];
}
@end


// Code
NSDictionary *dictionary = /* parse the JSON response to a dictionary */;
ProductCategory *category = [[ProductCategory alloc] initWithDictionary:dictionary];

// Log
category.name // => 1
category.children // => <NSArray>
[category.children count] // => 3
[category.children objectAtIndex:1] // => <ProductCategory>
[[category.categories objectAtIndex:1] name] // => 1.2

[[[category.children objectAtIndex:1] children] objectAtIndex:0] // => <ProductCategory>
[[[[category.children objectAtIndex:1] children] objectAtIndex:0] name] // => 1.2.1.2

Custom mapping

If you are receiving a json from a web server:

{
	"first_name": "John",
	"last_name": "Doe"
}
// Person.h
@interface Person : Jastor
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@end

// Person.m
@implementation Person
@synthesize firstName, lastName;

- (void)dealloc {
	[firstName release]; firstName = nil;
	[lastName release]; lastName = nil;

	[super dealloc];
}

- (NSDictionary *)map{
    NSMutableDictionary *map = [NSMutableDictionary dictionaryWithDictionary:[super map]];
    [map setObject:@"first_name" forKey:@"firstName"];
    [map setObject:@"last_name" forKey:@"lastName"];
    return [NSDictionary dictionaryWithDictionary:map];
}

@end

// Code
NSDictionary *dictionary = /* parse the JSON response to a dictionary */;
Person *person = [[Person alloc] initWithDictionary:dictionary];

// Log
person.firstName // => John
person.lastName // => Doe

How does it work?

Runtime API. The class's properties are read in runtime and assigns all values from dictionary to these properties with NSObject setValue:forKey:. For Dictionaries, Jastor instantiates a new class, based on the property type, and issues another initWithDictionary. Arrays are only a list of items such as strings (which are not converted) or dictionaries (which are treated the same as other dictionaries).

Installation

Just copy Jastor.m+.h and JastorRuntimeHelper.m+.h to your project, create a class, inherit, use the initWithDictionary and enjoy!

Testing

Make sure to initialize git submodules.

git submodules init
git submodules update

In Xcode, hit CMD+U under iPhone simulator scheme.

REALLY Good to know

What about properties that are reserved words?

As for now, id is converted to objectId automatically. Maybe someday Jastor will have ability to map server and obj-c fields.

Jastor classes also conforms to NSCoding protocol

So you get initWithCoder/encodeWithCoder for free.

You can look at the tests for real samples.

Alternatives

Contributors

More Repositories

1

next-with-less

Next.js + Less CSS Support
JavaScript
144
star
2

reuse-promise

Reuse the same promise that's returned from a function until it's resolved
JavaScript
103
star
3

isotope

Ruby Hybrid Template Engine for Client Side and Server Side, EJS-Based
Ruby
55
star
4

lodash-bound

Enables chained lodash functions with ES bind (::) syntax
JavaScript
39
star
5

class-private-method-decorator

Private methods in a JavaScript ES6 class using an ES7 decorator
JavaScript
30
star
6

rollup-plugin-preserve-shebangs

A Rollup plugin that preserves shebangs (#!/usr/bin/env node) in output files
TypeScript
17
star
7

hoist-non-react-methods

Copies non-react specific methods from a child component to a parent component
JavaScript
11
star
8

kaching

Makes your DB suffer less from COUNT(*) queries and check-for-existence queries of associations (has_many and has_many :through), by keeping and maintaining counts and lists on Redis, for faster access.
Ruby
7
star
9

sidekiq_custom_serializer

An extension for Sidekiq that brings custom serialization of arguments such as ActiveRecord instances, classes, modules and custom objects.
Ruby
3
star
10

mootools-trackinstances

Track Class Instances With a Class Mutator
JavaScript
2
star
11

fake-https-cert

JavaScript
1
star
12

react-ref-method-forwarder

Allows accessing methods of HOC-wrapped components through normal React refs
JavaScript
1
star
13

barcode

JavaScript
1
star
14

mootools-laziness

Class Mutator to reduce memory usage of class' prototype objects and function pointers unless an instance is instantiated
JavaScript
1
star