Coder Social home page Coder Social logo

jsonapi-ios's Introduction

JSONAPI - iOS

Build Status Join the chat at https://gitter.im/joshdholtz/jsonapi-ios

A library for loading data from a JSON API datasource. Parses JSON API data into models with support for linking of properties and other resources.

Quick Usage

NSDictionary *json = [self responseFromAPIRequest];
JSONAPI *jsonAPI = [JSONAPI jsonAPIWithDictionary:json];

ArticleResource *article = jsonAPI.resource;
NSLog(@"Title: %@", article.title);

For some full examples on how to use everything, please see the tests - https://github.com/joshdholtz/jsonapi-ios/blob/master/Project/JSONAPITests/JSONAPITests.m

Updates

Version Changes
1.0.7 Added meta and setMeta to JSONAPIResource and JSONAPIResourceBase (#43).
1.0.6 Improved resource parsing and added parsing of selfLinks (#35). Thanks to [ artcom](https://github.com/ artcom) for helping! Also removed the need to define setIdProperty and setSelfLinkProperty in every resource (automatically mapped in the init of JSONAPIResourceDescriptor)
1.0.5 Fix 1-to-many relationships serialization according to JSON API v1.0 (#34). Thanks to RafaelKayumov for helping!
1.0.4 Add support for empty to-one relationship according to JSON API v1.0 (#33). Thanks to RafaelKayumov for helping!
1.0.3 Add ability to map different types of objects (#32). Thanks to ealeksandrov for helping!
1.0.2 Just some bug fixes. Thanks to christianklotz for helping again!
1.0.1 Now safely checks for NSNull in the parsed JSON. Thanks to christianklotz for that fix!
1.0.0 We did it team! We are at the JSON API 1.0 final spec. Resources now use JSONAPIResourceDescriptor for more explicit definitions. HUGE thanks to jkarmstr for doing all the dirty work. Also thanks to edopelawi , BenjaminDigeon, and christianklotz for some bug fixes!
1.0.0-rc1 Rewrote core of JSONAPI and JSONAPIResource and all unit tests to be up to spec with JSON API spec 1.0.0-rc3. Removed JSONAPIResourceLinker. Added JSONAPIErrorResource
0.2.0 Added NSCopying and NSCoded to JSONAPIResource; Added JSONAPIResourceFormatter to format values before getting mapped - more info
0.1.2 JSONAPIResource IDs can either be numbers or strings (thanks danylhebreux); JSONAPIResource subclass can have mappings defined to set JSON values into properties automatically - more info
0.1.1 Fixed linked resources with links so they actually link to other linked resources
0.1.0 Initial release

Features

  • Allows resource types to be created into subclasses of JSONAPIResource
  • Set mapping for JSONAPIResource subclass to set JSON values and relationships into properties

Installation

Drop-in Classes

Clone the repository and drop in the .h and .m files from the "Classes" directory into your project.

CocoaPods

JSONAPI is available through CocoaPods, to install it simply add the following line to your Podfile:

pod 'JSONAPI', '~> 1.0.7'

Classes/protocols

For some full examples on how to use everything, please see the tests - https://github.com/joshdholtz/jsonapi-ios/blob/master/Project/JSONAPITests/JSONAPITests.m

JSONAPI

JSONAPI parses and validates a JSON API document into a usable object. This object holds the response as an NSDictionary but provides methods to accomdate the JSON API format such as meta, errors, linked, resources, and includedResources.

JSONAPIResource

Protocol of an object that is available for JSON API serialization. When developing model classes for use with JSON-API, it is suggested that classes be derived from JSONAPIResourceBase, but that is not required. An existing model class can be adapted for JSON-API by implementing this protocol.

JSONAPIResourceBase

JSONAPIResourceBase is an object (that gets subclassed) that holds data for each resource in a JSON API document. This objects holds the "id" as ID and link for self as selfLink as well as attributes and relationships defined by descriptors (see below)

JSONAPIResourceDescriptor

+ (JSONAPIResourceDescriptor*)descriptor should be overwritten to define descriptors for mapping of JSON keys and relationships into properties of a subclassed JSONAPIResource.

Full Example

ViewController.m

NSDictionary *json = [self responseFromAPIRequest];
JSONAPI *jsonAPI = [JSONAPI jsonAPIWithDictionary:json];

ArticleResource *article = jsonAPI.resource;
NSLog(@"Title: %@", article.title);
NSLog(@"Author: %@ %@", article.author.firstName, article.author.lastName);
NSLog(@"Comment Count: %ld", article.comments.count);

ArticleResource.h

@interface ArticleResource : JSONAPIResourceBase

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) PeopleResource *author;
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, strong) NSArray *comments;

@end

ArticleResource.m

@implementation ArticleResource

static JSONAPIResourceDescriptor *__descriptor = nil;

+ (JSONAPIResourceDescriptor*)descriptor {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        __descriptor = [[JSONAPIResourceDescriptor alloc] initWithClass:[self class] forLinkedType:@"articles"];

        [__descriptor addProperty:@"title"];
        [__descriptor addProperty:@"date"
                 withDescription:[[JSONAPIPropertyDescriptor alloc] initWithJsonName:@"date" withFormat:[NSDateFormatter RFC3339DateFormatter]]];

        [__descriptor hasOne:[PeopleResource class] withName:@"author"];
        [__descriptor hasMany:[CommentResource class] withName:@"comments"];
    });

    return __descriptor;
}

@end

PeopleResource.h

@interface PeopleResource : JSONAPIResourceBase

@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSString *twitter;

@end

PeopleResource.m

@implementation PeopleResource

static JSONAPIResourceDescriptor *__descriptor = nil;

+ (JSONAPIResourceDescriptor*)descriptor {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        __descriptor = [[JSONAPIResourceDescriptor alloc] initWithClass:[self class] forLinkedType:@"people"];

        [__descriptor addProperty:@"firstName" withDescription:[[JSONAPIPropertyDescriptor alloc] initWithJsonName:@"first-name"]];
        [__descriptor addProperty:@"lastName" withJsonName:@"last-name"];
        [__descriptor addProperty:@"twitter"];
    });

    return __descriptor;
}

@end

CommentResource.h

@interface CommentResource : JSONAPIResourceBase

@property (nonatomic, strong) NSString *text;
@property (nonatomic, strong) PeopleResource *author;

@end

CommentResource.m

@implementation CommentResource

static JSONAPIResourceDescriptor *__descriptor = nil;

+ (JSONAPIResourceDescriptor*)descriptor {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        __descriptor = [[JSONAPIResourceDescriptor alloc] initWithClass:[self class] forLinkedType:@"comments"];

        [__descriptor addProperty:@"text" withJsonName:@"body"];

        [__descriptor hasOne:[PeopleResource class] withName:@"author"];
    });

    return __descriptor;
}

@end

Advanced

How to do custom "sub-resources" mappings

Sometimes you may have parts of a resource that need to get mapped to something more specific than just an NSDictionary. Below is an example on how to map an NSDictionary to non-JSONAPIResource models.

We are essentially creating a property descriptor that maps to a private property on the resource. We then override that properties setter and do our custom mapping there.

Resource part of JSON API Response

"attributes":{
  "title": "Something something blah blah blah"
  "image": {
    "large": "http://someimageurl.com/large",
    "medium": "http://someimageurl.com/medium",
    "small": "http://someimageurl.com/small"
  }
}

ArticleResource.h

@interface ArticleResource : JSONAPIResourceBase

@property (nonatomic, strong) NSString *title;

// The properties we are pulling out of a a "images" dictionary
@property (nonatomic, storng) NSString *largeImageUrl;
@property (nonatomic, storng) NSString *mediumImageUrl;
@property (nonatomic, storng) NSString *smallImageUrl;

@end

ArticleResource.m

@interface ArticleResource()

// Private variable used to store raw NSDictionary
// We will override the setter and set our custom properties there
@property (nonatomic, strong) NSDictionary *rawImage;

@end

@implementation ArticleResource

static JSONAPIResourceDescriptor *__descriptor = nil;

+ (JSONAPIResourceDescriptor*)descriptor {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        __descriptor = [[JSONAPIResourceDescriptor alloc] initWithClass:[self class] forLinkedType:@"articles"];

        [__descriptor addProperty:@"title"];
        [__descriptor addProperty:@"rawImage" withDescription:[[JSONAPIPropertyDescriptor alloc] initWithJsonName:@"image"]];

    });

    return __descriptor;
}

- (void)setRawImage:(NSDictionary*)rawImage {
  _rawImage = rawImage;

  // Pulling the large, medium, and small urls out when
  // this property gets set by the JSON API parser
  _largeImageUrl = _rawImage[@"large"];
  _mediumImageUrl = _rawImage[@"medium"];
  _smallImageUrl = _rawImage[@"small"];
}

@end

Author

Josh Holtz, [email protected], @joshdholtz

License

JSONAPI is available under the MIT license. See the LICENSE file for more info.

jsonapi-ios's People

Contributors

benjamindigeon avatar christianklotz avatar ealeksandrov avatar jamesbrooks avatar jkarmstr avatar jkrumow avatar rafaelkayumov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jsonapi-ios's Issues

Initializer call is missing

In file JSONAPIResourceParser.m at line 59:

NSObject <JSONAPIResource> *resource = [[descriptor resourceClass] alloc];

has to be:

NSObject <JSONAPIResource> *resource = [[[descriptor resourceClass] alloc] init];

Add support for using protocol instead of subclassing for model files

It would be nice if we don't have to subclass JSONAPIResource for our model files. Because we are subclassing our model files with our own base class already. We could then use this pod if the whole system also supports some kind of protocol. So our model files just simply implements the protocol.

JSON API RC3 tracking

Hey there! I just wanted to let you know that JSON API has hit RC3, and we'd like client libraries to start implementing it like it was 1.0, as a final check that we're good for 1.0. I wanted to make this issue to let you know!

json-api/json-api#484

Linking resources of the same kind.

Hello! Thanks for the library.

Today I ran into a problem using this library hopefully anyone can help me.

Lets say I have a resource

{
      "id": "29",
      "type": "ediary_entry_groups",
      "attributes": {
        ...
      },
      "relationships": {
        "child_entry_groups": {
          "data": [
            {
              "id": "30",
              "type": "ediary_entry_groups"
            },
            {
              "id": "31",
              "type": "ediary_entry_groups"
            },
            {
              "id": "32",
              "type": "ediary_entry_groups"
            },
            {
              "id": "33",
              "type": "ediary_entry_groups"
            }
          ]
        },
        "parent_entry_group": {
          "data": null
        }
      }

When trying to link the relationship for child_entry_groups the parser is using the includedResources to search for those relationships

+ (void)link:(NSObject <JSONAPIResource>*)resource withIncluded:(JSONAPI*)jsonAPI {
    
    NSDictionary *included = jsonAPI.includedResources;

But in my case all the values for the relationships are inside the data and I was thinking if we could include the data to search for possible values for relationships also. I hope I'm being clear enough please let me know if you need more information.

Here is a link of the response Im trying to parse.

EDIT: How does this library parse relationships for the same type of resource ( The resource in the relationship is inside data not included ) ?

Missing top level data field during serialization?

Hi, Thank for this library. Just not sure if I'm serializing correctly as I'm missing the top level data field as required by JSON API spec 1.0.

let dict = JSONAPIResourceParser.dictionaryFor(object)

Parser crash if resource descriptor not defined

When a ressource descriptor is not defined the JSONAPIResourceParser crash

The problem is in JSONAPIResourceParser.m on the branch json-api-v1.0-final

+ (id <JSONAPIResource>)parseResource:(NSDictionary*)dictionary {
    NSString *type = dictionary[@"type"] ?: @"";
    JSONAPIResourceDescriptor *descriptor = [JSONAPIResourceDescriptor forLinkedType:type];

    NSObject <JSONAPIResource> *resource = [[descriptor resourceClass] alloc];
    [self set:resource withDictionary:dictionary];

    return resource;
}

If an JSONAPIResourceDescriptor is not defined by for the ressource then parseResource return nil

And adding nil to an NSMutableArray

+ (NSArray*)parseResources:(NSArray*)array {

    NSMutableArray *mutableArray = @[].mutableCopy;
    for (NSDictionary *dictionary in array) {
        [mutableArray addObject:[self parseResource:dictionary]];
    }

    return mutableArray;
}

Give a nice

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

If a ressource descriptor is not defined for a ressource it should be ignored not crashing the app.

Resource metadata

Is there any way to access the meta object of an included resource:

"included": [ { "meta": { "unresolved": "This is a test message" }, "id": "93ae7543-3ae1-417f-8feb-51217b5f4d01", "type": "participants" },

I've tried adding "meta" as a property and as a "hasOne" relationship, but that didn't work.

Thank you

Wrong getter for ID property

Found several places where resource ID property is referenced this way:

resource.ID

Suppose that the correct way would be:

JSONAPIResourceDescriptor *desc = <get resource descriptor somehow>;
...
[[resource valueForKey:desc.idProperty] blah];

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.