From JSON to Core Data and back.

Overview

Groot

Carthage compatible

Groot provides a simple way of serializing Core Data object graphs from or into JSON.

It uses annotations in the Core Data model to perform the serialization and provides the following features:

  1. Attribute and relationship mapping to JSON key paths.
  2. Value transformation using named NSValueTransformer objects.
  3. Object graph preservation.
  4. Support for entity inheritance

Installing Groot

Using CocoaPods

Add the following to your Podfile:

use_frameworks!
pod 'Groot'

Or, if you need to support iOS 6 / OS X 10.8:

pod 'Groot/ObjC'

Then run $ pod install.

If you don’t have CocoaPods installed or integrated into your project, you can learn how to do so here.

Using Carthage

Add the following to your Cartfile:

github "gonzalezreal/Groot"

Then run $ carthage update.

Follow the instructions in Carthage’s README to add the framework to your project.

You may need to set Embedded Content Contains Swift Code to YES in the build settings for targets that only contain Objective-C code.

Getting started

Consider the following JSON describing a well-known comic book character:

{
    "id": "1699",
    "name": "Batman",
    "real_name": "Bruce Wayne",
    "powers": [
        {
            "id": "4",
            "name": "Agility"
        },
        {
            "id": "9",
            "name": "Insanely Rich"
        }
    ],
    "publisher": {
        "id": "10",
        "name": "DC Comics"
    }
}

We could translate this into a Core Data model using three entities: Character, Power and Publisher.

Model

Mapping attributes and relationships

Groot relies on the presence of certain key-value pairs in the user info dictionary associated with entities, attributes and relationships to serialize managed objects from or into JSON. These key-value pairs are often referred in the documentation as annotations.

In our example, we should add a JSONKeyPath in the user info dictionary of each attribute and relationship specifying the corresponding key path in the JSON:

  • id for the identifier attribute,
  • name for the name attribute,
  • real_name for the realName attribute,
  • powers for the powers relationship,
  • publisher for the publisher relationship,
  • etc.

Attributes and relationships that don't have a JSONKeyPath entry are not considered for JSON serialization or deserialization.

Value transformers

When we created the model we decided to use Integer 64 for our identifier attributes. The problem is that, for compatibility reasons, the JSON uses strings for id values.

We can add a JSONTransformerName entry to each identifier attribute's user info dictionary specifying the name of a value transformer that converts strings to numbers.

Groot provides a simple way for creating and registering named value transformers:

// Swift

func toString(_ value: Int) -> String? {
    return String(value)
}

func toInt(_ value: String) -> Int? {
    return Int(value)
}

ValueTransformer.setValueTransformer(withName: "StringToInteger", transform: toInt, reverseTransform: toString)
// Objective-C

[NSValueTransformer grt_setValueTransformerWithName:@"StringToInteger" transformBlock:^id(NSString *value) {
    return @([value integerValue]);
} reverseTransformBlock:^id(NSNumber *value) {
    return [value stringValue];
}];

Object graph preservation

To preserve the object graph and avoid duplicating information when serializing managed objects from JSON, Groot needs to know how to uniquely identify your model objects.

In our example, we should add an identityAttributes entry to the Character, Power and Publisher entities user dictionaries with the value identifier.

Adding the identityAttributes annotation to your entities can affect performance when serializing from JSON. For more information see Object Uniquing Performance.

For more information about annotating your model have a look at Annotations.

Serializing from JSON

Now that we have our Core Data model ready we can start adding some data.

// Swift

let batmanJSON: JSONDictionary = [
    "name": "Batman",
    "id": "1699",
    "powers": [
        [
            "id": "4",
            "name": "Agility"
        ],
        [
            "id": "9",
            "name": "Insanely Rich"
        ]
    ],
    "publisher": [
        "id": "10",
        "name": "DC Comics"
    ]
]

do {
    let batman: Character = try object(fromJSONDictionary: batmanJSON, inContext: context)
} catch let error as NSError {
    // handle error
}
// Objective-C

Character *batman = [GRTJSONSerialization objectWithEntityName:@"Character"
                                            fromJSONDictionary:batmanJSON
                                                     inContext:self.context
                                                         error:&error];

If we want to update the object we just created, Groot can merge the changes for us:

// Swift

let updateJSON: JSONDictionary = [
    "id": "1699",
    "real_name": "Bruce Wayne",
]

do {
    // This will return the previously created managed object
    let batman: Character = try object(fromJSONDictionary: updateJSON, inContext: context)
} catch let error as NSError {
    // handle error
}

Serializing relationships from identifiers

Suppose that our API does not return full objects for the relationships but only the identifiers.

We don't need to change our model to support this situation:

// Swift

let batmanJSON: JSONDictionary = [
    "name": "Batman",
    "real_name": "Bruce Wayne",
    "id": "1699",
    "powers": ["4", "9"],
    "publisher": "10"
]

do {
    let batman: Character = try object(fromJSONDictionary: batmanJSON, inContext: context)
} catch let error as NSError {
    // handle error
}

The above code creates a full Character object and the corresponding relationships pointing to Power and Publisher objects that just have the identifier attribute populated.

We can import powers and publisher from different JSON objects and Groot will merge them nicely:

// Swift

let powersJSON: JSONArray = [
    [
        "id": "4",
        "name": "Agility"
    ],
    [
        "id": "9",
        "name": "Insanely Rich"
    ]
]

let publisherJSON: JSONDictionary = [
    "id": "10",
    "name": "DC Comics"
]

do {
    let _: [Power] = try objects(fromJSONArray: powersJSON, inContext: context)
    let _: Publisher = try object(fromJSONDictionary: publisherJSON, inContext: context)
} catch let error as NSError {
    // handle error
}

Note that serializing relationships from identifiers only works with entities specifying only one attribute as the value of identityAttributes annotation.

For more serialization alternatives check Groot.swift and GRTJSONSerialization.h.

Entity inheritance

Groot supports entity inheritance via the entityMapperName annotation.

If you are using SQLite as your persistent store, Core Data implements entity inheritance by creating one table for the parent entity and all child entities, with a superset of all their attributes. This can obviously have unintended performance consequences if you have a lot of data in the entities, so use this feature wisely.

Object Uniquing Performance

Object uniquing can affect performance when serialising from JSON, as it requires fetching data from the database before inserting.

If you take a look on how Groot is implemented, there are three serialization strategies:

  • Insert
  • Uniquing
  • Composite Uniquing

As you may guess, the first one is the most performant as it does not fetch from the database. If you know that there is no duplicate data in your data set, DO NOT set identityAttributes in your entity. This will make Groot use the Insert strategy.

Groot will pick the Uniquing strategy if the identityAttributes annotation has a single attribute, otherwise it will pick the Composite Uniquing strategy.

The Uniquing strategy requires one fetch for every array of JSON objects, whereas the Composite Uniquing strategy requires one fetch for every single JSON object (it is potentially the slowest of the three strategies).

Serializing to JSON

Groot provides methods to serialize managed objects back to JSON:

// Swift

let result = json(fromObject: batman)
// Objective-C

NSDictionary *JSONDictionary = [GRTJSONSerialization JSONDictionaryFromObject:batman];

For more serialization alternatives check Groot.swift and GRTJSONSerialization.h.

Contact

Guillermo Gonzalez
@gonzalezreal

License

Groot is available under the MIT license.

Comments
  • Attribute validation when using merge method

    Attribute validation when using merge method

    When using mergeObjectForEntityName:..., I see that updated entities are not validated if the value isnil. This happens at line 285 inGRTJSONSerialization.m`:

        if (merge && value == nil) {
            return YES;
        }
    

    Now the problem is that when merging, I sometime have new object to insert. But if those new objects have an empty field, they are not validated. So if I have a non-optional attribut in a newly inserted object, and the value is nil, no error is created.

    Could there be a way, when using the mergemethod, so that attributes in objects to insert are using the validation process, even if nil?

    bug 
    opened by FranckLetellier 10
  • Groot fails to build under Xcode 7.1

    Groot fails to build under Xcode 7.1

    Building Groot fails under Xcode 7.1 with the error

    Include of non-modular header inside framework module 'Groot.Groot'

    The cause of the issue is the way headers are included in Groot.h file:

    #import <Groot/GRTError.h>
    #import <Groot/GRTManagedStore.h>
    #import <Groot/NSValueTransformer+Groot.h>
    #import <Groot/GRTJSONSerialization.h>
    

    Changing the includes to

    #import "GRTError.h"
    #import "GRTManagedStore.h"
    #import "NSValueTransformer+Groot.h"
    #import "GRTJSONSerialization.h"
    

    fixes the issue.

    opened by o15a3d4l11s2 9
  • Merging with deletion

    Merging with deletion

    After evaluating tons of Core Data wrappers and object mappers I came across Groot and I'm really happy with its simplicity and approach.

    My application has a one-way connection (so it's read-only) to a REST API to display some sort of news feed. I'm currently using the mergeObjectsForEntityName method to update my local Core Data store with data from the API. As expected, this does NOT remove items from Core Data which are no longer in the server's response. Is this a feature which could be incorporated into Groot or can you suggest a way of implementing this in my own code? I don't want to wipe out my whole Core Data entity and use insertObjectsForEntityName because my entities store additional meta data.

    Thanks! :)

    question 
    opened by soulchild 8
  • Fixes an issue that caused attributes to be updated even when their values are equal

    Fixes an issue that caused attributes to be updated even when their values are equal

    This fixes an issue that caused CoreData to issue a update query to every object fetched by Groot even if their values have not changed since the last fetch.

    opened by Rogiel 6
  • Identity attribute relationships

    Identity attribute relationships

    If your JSON has the relationships by referencing the identity attribute instead of by nesting JSONs, you can take advantage of the identityAttributeRelated attribute. For example, if your JSON NSDictionary is:

    NSDictionary *batman = @{
          @"id": @"1",
          @"name": @"Batman",
          @"publisher": @"1"
          }
    

    you may not want Groot to serialize this dictionary by setting 1 to the Publisher relationship, but by assigning it with the Publisher object which has 1 as its identityAttribute value. You accomplish that by associating the identityAttribute key with true (or any other positive boolean value) in the entity user info dictionary:

    Entity User Info

    This way, Groot will search in the publisher entity for a entry with the given identity attribute. If it is found, it will assign this entry as the Publisher object of the Character; if it doesn't Groot will create a placeholder Publisher entry with this value for the identity attribute. This placeholder object would be filled eventually if the new data is provided.

    Note: To make this feature works, you must always to use the merge methods instead of the insert ones.

    opened by ManueGE 6
  • How To Value Transformers?

    How To Value Transformers?

    Can you give us an example of how to use value transformers for say an NSDate coming with "yyyy-MM-dd'T'HH:mm:ssZ" format from/to the server.

    I saw in the documents that it's an attribute you set in the inspector, however how and where do I add the actual value transformer ?? In the model class or ???

    question 
    opened by kikolobo 5
  • possible to use managed the object's 'objectID' as a JSONKeyPath?

    possible to use managed the object's 'objectID' as a JSONKeyPath?

    I do not have an explicit id field in any of my core data entities, but I would like to have a unique identifier for serialization -- in my application I use the NSManagedObject objectID property as the unique identifier, is it possible to have Groot serialize it along with the rest of my fields?

    question 
    opened by amitailanciano 4
  • Polymorphic relationships

    Polymorphic relationships

    I have a JSON blob like this:

    [
        { 
            "id": 1,
            "title": "Audio Title",
            "type": "audio",
        },
        {
            "id": 2,
            title: "Video Title",
            type: "video",
        }
    ]
    

    I'm no Core Data expert, but I suppose it's possible to have a common Media base class entity with two entity subclasses for Video and Audio objects? If so, do you think Groot will be able to correctly deserialize the JSON blob above into Video and Audio object entities respectively based on the type property?

    Thanks!

    question 
    opened by soulchild 4
  • How to serialize back to JSON only some properties of a NSManaged object.

    How to serialize back to JSON only some properties of a NSManaged object.

    Hi,

    Is there a way for Groot to serialize back to JSON Dictionary only some properties of my NSManaged Object?

    Also, I want to know if it's possible to serialize from JSON some properties and to not serial back to JSON all of those properties. For example the createdAt time stamp that is created by the server.

    question 
    opened by kikolobo 4
  • GRTUniquingSerializationStrategy: attribute with null value replaces original value

    GRTUniquingSerializationStrategy: attribute with null value replaces original value

    I have NSManagedObject with identity attribute. This object has several nullable properties. I set values for these properties and save NSManagedObjectContext. When I get JSON from server containing list of objects I want to merge these changes with my existing objects. Although corresponding attributes are null my saved properties are replaced with these nulls.

    I looked through your code and found the following bug in file "NSManagedObject+Groot.m" line 167:

    if (rawValue != nil) {
         if (rawValue != [NSNull null]) {
            NSValueTransformer *transformer = [attribute grt_JSONTransformer];
            if (transformer) {
                value = [transformer transformedValue:rawValue];
            } else {
                value = rawValue;
            }
        }
    } else if (mergeChanges) {
            // Just validate the current value
            value = [self valueForKey:attribute.name];
            [self validateValue:&value forKey:attribute.name error:outError];  
    
            return;
        }
    

    So my case is not correctly processed by this code.

    Could you replace it with:

    if (rawValue != nil && rawValue != [NSNull null]) {
            NSValueTransformer *transformer = [attribute grt_JSONTransformer];
            if (transformer) {
                value = [transformer transformedValue:rawValue];
            } else {
                value = rawValue;
            }
    } else if (mergeChanges) {
            // Just validate the current value
            value = [self valueForKey:attribute.name];
            [self validateValue:&value forKey:attribute.name error:outError];
    
            return;
        }
    
    opened by ValentinStrazdin 3
  • Swift3

    Swift3

    Having some issues running on legacy versions of Swift, latest version of Xcode 8 requires an automatic conversion of certain projects using legacy Swift versions - about 95% converts correctly but there are still some compile issues with Groot.

    Update

    For those using CocoaPods and have just upgraded to Xcode 8 using iOS10 for project, specify the version of swift in your project and there shouldn't be an issue with Groot.

    post_install do |installer|
      installer.pods_project.build_configuration_list.build_configurations.each do |configuration|
      configuration.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
        configuration.build_settings['SWIFT_VERSION'] = '2.3'
      end
    end
    
    opened by cjjenkinson 3
  • Automatically mapping properties with the same name

    Automatically mapping properties with the same name

    I love Groot 👏. Once thing it would make me love it even more is that properties in the JSON are automatically mapped to properties in the Entities without the need of annotations. Many times I find myself adding a JSONKeyPath to map 2 properties that use the same name. I guess you have thought about this but I guess there’s a reason to not have it that way, is that right?

    In case there isn’t one, I forked your repo and I’m working on implementing it. If you think that’s something you’d be interesting in merging, please let me know.

    opened by juanjo-ramos 0
  • Ability to modify objects after being imported using Groot

    Ability to modify objects after being imported using Groot

    Hello!

    After using Groot for years I found a small improvement. Could we add a way to modify an object after it is parsed with Groot? Let me explain.

    Let's say I have these entities:

    User
        - id
        - name
        - role
    
    Role
       - id
       - name
       - importedFromServer
    
    Department
       - id
       - name
       - users
    

    I would like to set the importedFromServer to true after every Groot import. I know that currently I can do it this way:

    let role: Role = try object(fromJSONDictionary: dictionary, inContext: context)
    role.importedFromServer = true
    

    This is quite easy, but it the thing I import is a user, I need to do:

    let user: User = try object(fromJSONDictionary: dictionary, inContext: context)
    user.role.importedFromServer = true
    

    And if I import a Department:

    let department: Department = try object(fromJSONDictionary: dictionary, inContext: context)
    department.users.forEach { $0.role.importedFromServer = true }
    

    NOTE: This is just a silly example. Indeed I know I could do achieve this just by adding an entity transformer and adding the importedFromServer key to the entity dictionary. But again, this is just an example, what I want to actually achieve is not doable this way.

    It would be great if we can do it in a single place.

    My proposal for doing it is creating a NSManagedObject extension with a single empty method:

    - (void) grt_awakeFromImport:(NSDictionary *) dictionary {
    }
    

    and call it after an object is inserted.

    This way any NSManagedObject subclass can override this method and do their own stuff there. In our example, we can add this method to Role:

    - (void) grt_awakeFromImport:(NSDictionary *) dictionary {
        self.importedFromServer = YES;
    }
    

    I can prepare a PR if you are willing to approve this feature.

    Let me know your thoughts.

    Thanks.

    opened by ManueGE 2
  • Parsing Boolean value fails

    Parsing Boolean value fails

    I'm using Groot for quite some time now and lately I have experienced a quite strange problem.

    I'm mapping JSON var not_found on a Core Data attribute isNotFound. Within the attached JSON there are 4 line-item entities, two of them with not_found = true and another two with not_found = false. My problem is that all entities are parsed correctly except for the one with id == 504330. Even though its not_found is true it's parsed as false (which is the attribute's default value in Core Data). So it's either not parsed correctly, or not parsed at all. However, object with id == 504333 that also has its not_found set to true is parsed correctly.

    Here's the JSON:

    [{
     "id": "504333",
     "added_by_shopper": false,
     "added_by_customer_support": false,
     "description": null,
     "shopped_at": null,
     "sorted_at": null,
     "replacement_type": null,
     "replacement_chosen_by": null,
     "not_found": true,
     "customer_replacement_request": null,
     "storage_temperature": null,
     "name": "Zaeli Cassava Starch Sour 500G",
     "quantity": 2,
     "quantity_shopped": 0,
     "quantity_sorted": 0,
     "quantity_cancelled": 0,
     "customer_notes": null,
     "position": 1000.0,
     "aisle_name": "Uncategorised",
     "replacement": null,
     "product_id": "0001",
     "order_id": "0001",
     "price": 1.1,
     "images": null,
     "replacement_suggestions": [],
     "replacement_options": [],
     "customer_replacement_requests": []
     },
     {
     "id": "504332",
     "added_by_shopper": false,
     "added_by_customer_support": false,
     "description": null,
     "shopped_at": "2018-06-29T15:39:46.522+01:00",
     "sorted_at": null,
     "replacement_type": null,
     "replacement_chosen_by": null,
     "not_found": false,
     "customer_replacement_request": null,
     "storage_temperature": null,
     "name": "Granulated Sugar 5Kg",
     "quantity": 1,
     "quantity_shopped": 1,
     "quantity_sorted": 0,
     "quantity_cancelled": 0,
     "customer_notes": null,
     "position": 1000.0,
     "aisle_name": "Uncategorised",
     "replacement": null,
     "product_id": "0002",
     "order_id": "0001",
     "price": 3.15,
     "images": null,
     "replacement_suggestions": [],
     "replacement_options": [],
     "customer_replacement_requests": []
     },
     {
     "id": "504331",
     "added_by_shopper": false,
     "added_by_customer_support": false,
     "description": "Chicken stock cube.",
     "shopped_at": "2018-06-29T15:42:30.422+01:00",
     "sorted_at": null,
     "replacement_type": null,
     "replacement_chosen_by": null,
     "not_found": false,
     "customer_replacement_request": null,
     "storage_temperature": null,
     "name": "Tesco 10 Chicken Stock Cubes 100G",
     "quantity": 3,
     "quantity_shopped": 3,
     "quantity_sorted": 0,
     "quantity_cancelled": 0,
     "customer_notes": null,
     "position": 52.0,
     "aisle_name": "Gravy, Stocks & Stuffing",
     "replacement": null,
     "product_id": "0003",
     "order_id": "0001",
     "price": 0.5,
     "images": null,
     "replacement_suggestions": [],
     "replacement_options": [],
     "customer_replacement_requests": []
     },
     {
     "id": "504330",
     "added_by_shopper": false,
     "added_by_customer_support": false,
     "description": "Carioca beans",
     "shopped_at": "2018-06-29T15:46:47.273+01:00",
     "sorted_at": null,
     "replacement_type": null,
     "replacement_chosen_by": null,
     "not_found": true,
     "customer_replacement_request": null,
     "storage_temperature": null,
     "name": "Camil Carioca Beans/Feijao Carioca 1Kg",
     "quantity": 10,
     "quantity_shopped": 7,
     "quantity_sorted": 0,
     "quantity_cancelled": 0,
     "customer_notes": null,
     "position": 1000.0,
     "aisle_name": "Uncategorised",
     "replacement": null,
     "product_id": "0004",
     "order_id": "0001",
     "price": 1.5,
     "images": null,
     "replacement_suggestions": [],
     "replacement_options": [],
     "customer_replacement_requests": []
     }
     ]
    

    And here's the isNotFound Core Data attribute after parsing:

    id: 504333 | isNotFound: true
    id: 504332 | isNotFound: false
    id: 504331 | isNotFound: false
    id: 504330 | isNotFound: false
    
    opened by EvansPie 0
  • Could not locate the entity for \(className) even though it exists

    Could not locate the entity for \(className) even though it exists

    I installed Groot via cocoapods and using xcode 9.3, swift 4.

    When I Call:

    let context = NSManagedObjectContext.mr_default()
    let _: [MObject] = try objects(fromJSONArray: correctedJSON, inContext: context)
    

    It throws the fatalError I can't explain to my self why. this object exists. Any ideas?

    opened by mariusschoenefeld 5
  • Prevent infinite recursion when Groot traverses complex data model?

    Prevent infinite recursion when Groot traverses complex data model?

    Hi,

    We're trying to use Groot to serialize and deserialize our main data object class. It is a complex managed object with many relationships. In turn, many of its related objects are related to each other and to other nested objects. That means that there are 10-15 entities that are intertwined with forward and reverse relationships.

    I've started testing Groot with our real-world data and immediately encountered a crash because Groot was recursing infinitely amidst our intertwined relationships. I have been able to prevent that by removing the JSONKeyPath user info on a few reverse relationships. This makes me wonder if I'm missing something in the way we've adopted Groot. I do have identityAttributes on all of our entities (applied to the entities themselves...is that correct?) Is there something else needed to convince Groot to stop parsing the object hierarchy when it reaches objects that were already parsed previously?

    Thanks for any suggestions you can give me...Groot is amazing and we're really hoping to get it fully functional in our app. :)

    David

    bug help wanted 
    opened by dhearst 6
Releases(3.0.1)
Owner
Guille Gonzalez
Mobile developer. Converting coffee into code since the nineties. Comic book lover and movie buff.
Guille Gonzalez
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.

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

JSONModel 6.9k Dec 8, 2022
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.

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

JSONModel 6.8k Nov 19, 2021
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
Networking, JSON Parsing, APIs and Core Location

Clima Our Goal It’s time to take our app development skills to the next level. We’re going to introduce you to the wonderful world of Application Prog

Dessana Caldeira M. Santos 1 Nov 25, 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
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
AlamofireObjectMappe - An Alamofire extension which converts JSON response data into swift objects using ObjectMapper

AlamofireObjectMapper An extension to Alamofire which automatically converts JSON response data into swift objects using ObjectMapper. Usage Given a U

Tristan Himmelman 2.6k Dec 29, 2022
SwiftyJSON makes it easy to deal with JSON data in Swift.

SwiftyJSON SwiftyJSON makes it easy to deal with JSON data in Swift. Platform Build Status *OS Linux Why is the typical JSON handling in Swift NOT goo

SwiftyJSON 21.7k Jan 3, 2023
An extension for Alamofire that converts JSON data into Decodable objects.

Swift 4 introduces a new Codable protocol that lets you serialize and deserialize custom data types without writing any special code and without havin

Nikita Ermolenko 749 Dec 5, 2022
Coding Challenge using NYC JSON data

Coding Challenge using NYC JSON data This was my submission to JPMorgan's code challenge prior to an interview. It represents my solution to asyncrono

null 0 Dec 9, 2021
Nikolai Saganenko 1 Jan 9, 2022
A data visualisation tool that adds publicly available crime data from UK police forces to an interactive map.

CrimeMapper A data visualisation tool that adds publicly available crime data from UK police forces to an interactive map. Download on the App Store Y

sam woolf 11 Jul 20, 2022
Reflection based (Dictionary, CKRecord, NSManagedObject, Realm, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift

EVReflection General information At this moment the master branch is tested with Swift 4.2 and 5.0 beta If you want to continue using EVReflection in

Edwin Vermeer 964 Dec 14, 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
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