• Stars
    star
    150
  • Rank 242,386 (Top 5 %)
  • Language
    Swift
  • License
    MIT License
  • Created over 6 years ago
  • Updated almost 2 years ago

Reviews

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

Repository Details

Lightweight parser for the complex JSON:API (http://jsonapi.org/) structure.

Japx - JSON:API Decoder/Encoder

Build Status Version License Platform

Japx

Lightweight JSON:API parser that flattens complex JSON:API structure and turns it into simple JSON and vice versa. It works by transferring Dictionary to Dictionary, so you can use Codable, Unbox, Wrap, ObjectMapper or any other object mapping tool that you prefer.

Basic example

For given example of JSON object:

{
    "data": {
        "id": "1",
        "type": "users",
        "attributes": {
            "email": "[email protected]",
            "username": "john"
        }
    }
}

to parse it to simple JSON use:

let jsonApiObject: [String: Any] = ...
let simpleObject: [String: Any]

do {
    simpleObject = try JapxKit.Decoder.jsonObject(withJSONAPIObject: jsonApiObject)
} catch {
    print(error)
}

and parser will convert it to object where all properties inside attributes object will be flattened to the root of data object:

{
    "data": {
        "email": "[email protected]",
        "id": "1",
        "username": "john",
        "type": "users"
    }
}

Advanced examples

Parsing relationships

Simple Article object which has its Author:

{
    "data": [
        {
            "type": "articles",
            "id": "1",
            "attributes": {
                "title": "JSON API paints my bikeshed!",
                "body": "The shortest article. Ever.",
                "created": "2015-05-22T14:56:29.000Z",
                "updated": "2015-05-22T14:56:28.000Z"
            },
            "relationships": {
                "author": {
                    "data": {
                        "id": "42",
                        "type": "people"
                    }
                }
            }
        }
    ],
    "included": [
        {
            "type": "people",
            "id": "42",
            "attributes": {
                "name": "John",
                "age": 80,
                "gender": "male"
            }
        }
    ]
}

will be flattened to:

{
    "data": [
        {
            "updated": "2015-05-22T14:56:28.000Z",
            "author": {
                "age": 80,
                "id": "42",
                "gender": "male",
                "type": "people",
                "name": "John"
            },
            "id": "1",
            "title": "JSON API paints my bikeshed!",
            "created": "2015-05-22T14:56:29.000Z",
            "type": "articles",
            "body": "The shortest article. Ever."
        }
    ]
}

Parsing additional information

All nested object which do not have keys defined in JSON:API Specification will be left inside root object intact (same goes for links and meta objects):

{
    "data": [
        {
            "type": "articles",
            "id": "3",
            "attributes": {
                "title": "JSON API paints my bikeshed!",
                "body": "The shortest article. Ever.",
                "created": "2015-05-22T14:56:29.000Z",
                "updated": "2015-05-22T14:56:28.000Z"
            }
        }
    ],
    "meta": {
        "total-pages": 13
    },
    "links": {
        "self": "http://example.com/articles?page[number]=3&page[size]=1",
        "first": "http://example.com/articles?page[number]=1&page[size]=1",
        "prev": "http://example.com/articles?page[number]=2&page[size]=1",
        "next": "http://example.com/articles?page[number]=4&page[size]=1",
        "last": "http://example.com/articles?page[number]=13&page[size]=1"
    },
    "additional": {
        "info": "My custom info"
    }
}

Parsed JSON:

{
    "data": [
        {
            "updated": "2015-05-22T14:56:28.000Z",
            "id": "3",
            "title": "JSON API paints my bikeshed!",
            "created": "2015-05-22T14:56:29.000Z",
            "type": "articles",
            "body": "The shortest article. Ever."
        }
    ],
    "meta": {
        "total-pages": 13
    },
    "links": {
        "prev": "http://example.com/articles?page[number]=2&page[size]=1",
        "first": "http://example.com/articles?page[number]=1&page[size]=1",
        "next": "http://example.com/articles?page[number]=4&page[size]=1",
        "self": "http://example.com/articles?page[number]=3&page[size]=1",
        "last": "http://example.com/articles?page[number]=13&page[size]=1"
    },
    "additional": {
        "info": "My custom info"
    }
}

Parsing with include list

For defining which nested object you want to parse, you can use includeList parameter. For example:

{
    "data": {
        "type": "articles",
        "id": "1",
        "attributes": {
            "title": "JSON API paints my bikeshed!",
            "body": "The shortest article. Ever.",
            "created": "2015-05-22T14:56:29.000Z",
            "updated": "2015-05-22T14:56:28.000Z"
        },
        "relationships": {
            "author": {
                "data": {
                    "id": "42",
                    "type": "people"
                }
            }
        }
    },
    "included": [
        {
            "type": "people",
            "id": "42",
            "attributes": {
                "name": "John",
                "age": 80,
                "gender": "male"
            },
            "relationships": {
                "article": {
                    "data": {
                        "id": "1",
                        "type": "articles"
                    }
                }
            }
        }
    ]
}

Article and Author can be matched using include reference, as defined in JSON:API Specification:

let includeList: String = "author.article.author"
let jsonApiObject: [String: Any] = ...
let recursiveObject: [String: Any] = try JapxKit.Decoder.jsonObject(with: jsonApiObject, includeList: includeList)

Parsed JSON:

{
    "data": {
        "type": "articles",
        "id": "1",
        "title": "JSON API paints my bikeshed!",
        "body": "The shortest article. Ever.",
        "created": "2015-05-22T14:56:29.000Z",
        "updated": "2015-05-22T14:56:28.000Z",
        "author": {
            "type": "people",
            "id": "42",
            "name": "John",
            "age": 80,
            "gender": "male",
            "article": {
                "type": "articles",
                "id": "1",
                "title": "JSON API paints my bikeshed!",
                "body": "The shortest article. Ever.",
                "created": "2015-05-22T14:56:29.000Z",
                "updated": "2015-05-22T14:56:28.000Z",
                "author": {
                    "type": "people",
                    "id": "42",
                    "name": "John",
                    "age": 80,
                    "gender": "male"
                }
            }
        }
    }
}

Usage

Codable

Japx comes with wrapper for Swift Codable.

Since JSON:API object can have multiple additional fields like meta, links or pagination info, its real model needs to be wrapped inside data object. For easier parsing, also depending on your API specification, you should create wrapping native object which will contain your generic JSON model:

struct JapxResponse<T: Codable>: Codable {
    let data: T
    // ... additional info like: meta, links, pagination...
}

struct User: JapxCodable {
    let id: String
    let type: String
    let email: String
    let username: String
}

let userResponse: JapxResponse<User> = try JapxDecoder().decode(JapxResponse<User>.self, from: data)
let user: User = userResponse.data

where JapxDecodable and JapxEncodable are defined in JapxCodable file as:

/// Protocol that extends Decodable with required properties for JSON:API objects
protocol JapxDecodable: Decodable {
    var type: String { get }
    var id: String { get }
}

/// Protocol that extends Encodable with required properties for JSON:API objects
protocol JapxEncodable: Encodable {
    var type: String { get }
}

Codable and Alamofire

Japx also comes with wrapper for Alamofire and Codable which can be installed as described in installation chapter.

Use responseCodableJSONAPI method on DataRequest which will pass serialized response in callback. Also, there is keyPath argument to extract only nested data object. So, if you don't need any additional info from API side except plain data, than you can create simple objects, without using wrapping objects/structs.

struct User: JapxCodable {
    let id: String
    let type: String
    let email: String
    let username: String
}

Alamofire
    .request(".../api/v1/users/login", method: .post, parameters: [...])
    .validate()
    .responseCodableJSONAPI(keyPath: "data", completionHandler: { (response: DataResponse<User>) in
        switch response.result {
        case .success(let user):
            print(user)
        case .failure(let error):
            print(error)
        }
    })

Codable, Alamofire and RxSwift

Japx also comes with wrapper for Alamofire, Codable and RxSwift which can be installed as described in installation chapter.

Use responseCodableJSONAPI method from .rx extension on DataRequest which will return Single with serialized response.

let loginModel: LoginModel = ...
let executeLogin: ([String: Any]) throws -> Single<User> = {
    return Alamofire
        .request(".../api/v1/users/login", method: .post, parameters: $0)
        .validate()
        .rx.responseCodableJSONAPI(keyPath: "data")
}

return Single.just(loginModel)
        .map { try JapxEncoder().encode($0) }
        .flatMap(executeLogin)

Installation

Cocoapods

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

pod 'Japx'

We've also added some more functionalites like Alamofre or Moya for networking, Rx for reactive programming approach, Objective-C support:

# Alamofire
pod 'Japx/Alamofire'

# Alamofire and RxSwift
pod 'Japx/RxAlamofire'

# Moya
pod 'Japx/Moya'

# Moya and RxSwift
pod 'Japx/RxMoya'

# Objective-C
pod 'Japx/ObjC'

Unlike with other dependency managers below, you should always use:

import Japx

regardless of which custom integration you've picked.

platform :ios, '10.0'
use_frameworks!

target 'MyApp' do
  pod 'Japx/RxMoya'
end

Swift Package Manager

Add the dependency to your Package.swift and use in your target

dependencies: [
    .package(url: "https://github.com/infinum/Japx.git", .upToNextMajor(from: "4.0.0"))
]

Sample Package.swift

let package = Package(
    name: "YourDependency",
    products: [
        .library(name: "YourDependency", targets: ["YourDependency"])
    ],
    dependencies: [
        .package(url: "https://github.com/infinum/Japx.git", .upToNextMajor(from: "4.0.0")),
    ],
    targets: [
        .target(
            name: "YourDependency",
            dependencies: [.product(name: "Japx", package: "Japx")]
        )
    ]
)

We've also added some more functionalites like Alamofre or Moya for networking, Rx for reactive programming approach:

// Alamofire
.product(name: "JapxAlamofire", package: "Japx")

// Alamofire and RxSwift
.product(name: "JapxRxAlamofire", package: "Japx")

// Moya
.product(name: "JapxMoya", package: "Japx")

// Moya and RxSwift
.product(name: "JapxRxMoya", package: "Japx")

Depending on which product you've picked, you'll have to import different modules:

// Pure Japx
import Japx

// Alamofire
import JapxAlamofire

// Alamofire and RxSwift
import JapxRxAlamofire

// Moya
import JapxMoya

// Moya and RxSwift
import JapxRxMoya

Carthage

Run carthage update --use-xcframeworks and import desired integration. Pure Japx doesn't have any dependencies.

Imports work same as for Swift Package Manager, depending on which integration you've picked.

NOTE: Moya integration is currently not supported via Carthage since latest Moya build won't build with Carthage. More info here.

Example project

Example project of Japx networking using Codable and Alamofire can be found in Nuts And Bolts repository with commonly used code. Example will cover how to handle basic CRUD (Create, Read, Update, Delete) operations with Japx and JSON:API format. To run the example, clone the repository, open the Catalog.xcworkspace, run Catalog app and navigate to the Japx Networking section.

In this repository there is also a simple example project, to run it open Japx.xcodeproj and inspect Example directory and Japx_Example scheme.

Basic integrations with Cocoapods (run pod install), Swift Package Manager and Carthage can be found inside Examples directory.

Authors

Maintained by Infinum

Infinum

License

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

More Repositories

1

android_dbinspector

Android library for viewing, editing and sharing in app databases.
Kotlin
945
star
2

rails-handbook

Describing the development process used by the Infinum Rails Team.
Slim
763
star
3

FBAnnotationClustering

iOS library for clustering map notifications in an easy and performant way
Objective-C
713
star
4

Android-Goldfinger

Android library to simplify Biometric authentication implementation.
Java
652
star
5

ios-viper-xcode-templates

Used for generating template files for the VIPER architecture, which solves the common Massive View Controller issues in iOS apps.
HTML
576
star
6

phrasing

Edit phrases inline for your Ruby on Rails applications!
Ruby
544
star
7

eightshift-boilerplate

This repository contains all the tools you need to start building a modern WordPress theme, using all the latest front end development tools.
PHP
511
star
8

Android-GoldenEye

A wrapper for Camera1 and Camera2 API which exposes simple to use interface.
Kotlin
375
star
9

cookies_eu

Gem to add cookie consent to Rails application
Haml
266
star
10

dox

Automated API documentation from Rspec
Ruby
234
star
11

MjolnirRecyclerView

[DEPRECATED] This library is no longer maintained and it will not receive any more updates.
Java
220
star
12

ios-nuts-and-bolts

iOS bits and pieces that you can include in your project to make your life a bit easier.
Swift
195
star
13

flutter-charts

Customizable charts library for flutter.
Dart
139
star
14

datx

DatX is an opinionated JS/TS data store. It features support for simple property definition, references to other models and first-class TypeScript support.
TypeScript
137
star
15

learnQuery

Learn JavaScript fundamentals by building your own jQuery equivalent library
JavaScript
137
star
16

flutter-dasher

Dart
116
star
17

floggy

Customizable logger for dart and flutter applications.
Dart
115
star
18

android-complexify

An Android library which makes checking the quality of user's password a breeze.
Java
113
star
19

Android-Prince-of-Versions

Android library for handling application updates.
Java
104
star
20

android_connectionbuddy

Utility library for handling connectivity change events.
Java
94
star
21

eightshift-docs

A documentation website for Eightshift open source projects
JavaScript
79
star
22

eightshift-frontend-libs

Frontend library that exposes custom scripts and styles for modern WordPress projects
JavaScript
69
star
23

Retromock

Java library for mocking responses in a Retrofit service.
Kotlin
67
star
24

eightshift-libs

Library that is meant to be used inside Eightshift Boilerplate and Eightshift Boilerplate Plugin libs via composer in order to be able to easily set up a modern development process.
PHP
61
star
25

frontend-handbook

Our handbook based on 10 years of experience in Frontend/JS development
Slim
57
star
26

Locker

Securely lock your secrets under the watch of TouchID or FaceID keeper ๐Ÿ”’
Swift
50
star
27

emotion-normalize

normalize.css but for emotion.js
JavaScript
50
star
28

mobx-jsonapi-store

JSON API Store for MobX
TypeScript
48
star
29

Dagger-2-Example

Dagger 2 example project
Java
44
star
30

ios-prince-of-versions

Library used for easier versioning of your applications, allowing you to prompt your users to update the app to the newest version
Swift
43
star
31

enumerations

Better Rails Enumerations
Ruby
37
star
32

kotlin-jsonapix

JsonApiX is an Android, annotation processor library that was made to transform regular Kotlin classes into their JSON API representations, with the ability to serialize or deserialize them to or from strings.
Kotlin
36
star
33

eightshift-boilerplate-plugin

This repository contains all the tools you need to start building a modern WordPress plugin.
PHP
36
star
34

mobx-collection-store

Data collection store for MobX
TypeScript
35
star
35

android-sentinel

Sentinel is a simple one screen UI which provides a standardised entry point for tools used in development and QA alongside device, application and permissions data.
Kotlin
35
star
36

decoupled-json-content

JavaScript
30
star
37

wordpress-handbook

Official WordPress handbook at Infinum
Slim
30
star
38

webpack-asset-pipeline

๐Ÿš€ A missing link for the asset pipeline alternative with Webpack.
JavaScript
30
star
39

ios-loggie

Simplify debugging by showing network requests of your app as they happen.
Swift
30
star
40

flutter-plugins-locker

Flutter plugin that secures your secrets in keychain using biometric authentication (Fingerprint, Touch ID, Face ID...).
Dart
29
star
41

default_rails_template

Default template for generating new Rails applications.
Ruby
27
star
42

eightshift-forms

WordPress plugin project for Gutenberg forms
PHP
27
star
43

media-blender

Easy and predictable SASS/SCSS media queries
CSS
26
star
44

android-collar

Gradle plugin which collects all analytics screen names, events and user properties for Android projects.
Kotlin
26
star
45

secrets_cli

CLI for storing and reading your secrets via vault
Ruby
25
star
46

flutter-plugins-japx

JSON API parser for Flutter
Dart
24
star
47

flutter-bits

Flutter
Dart
22
star
48

react-mobx-translatable

Make React components translatable using MobX
JavaScript
21
star
49

dungeons-and-dragons

๐ŸŽฒ Dungeons & Dragons Character builder and keeper (work in progress)
TypeScript
19
star
50

android-crash-handler

Utility library which handles crash handler configuration
Java
19
star
51

qa-handbook

Describing the processes used by the Infinum QA Team
Slim
18
star
52

iOS-Bugsnatch

Swift
18
star
53

eightshift-coding-standards

Eightshift coding standards for WordPress
PHP
16
star
54

jsonapi-query_builder

Ruby
14
star
55

thrifty-retrofit-converter

Retrofit converter which uses Thrifty for Apache Thrift-compatible serialization
Java
13
star
56

json-wp-post-parser

JSON Post Parser plugin parses your content and saves it as JSON available in REST posts and pages endpoints.
PHP
13
star
57

swift-style-guide

12
star
58

generator-infinitely-static

๐Ÿ’ซ Static page generator with routes support thats infinitely awesome
JavaScript
11
star
59

react-responsive-ssr

TypeScript
11
star
60

JS-React-Example

Infinum's way of doing React
TypeScript
10
star
61

ngx-hal

Angular datastore library with HAL support
TypeScript
10
star
62

fiscalizer

A gem for fiscalizing invoices in Croatia using Ruby.
Ruby
9
star
63

ember-form-object

Form object pattern in ember apps
JavaScript
9
star
64

js-talks

โœจ Interesting talks and mini lectures about new and cool stuff that's going on in the world of JS development, organized by the Infinum JS team
9
star
65

android-handbook

Slim
8
star
66

js-linters

Infinum's JS team linter rules
TypeScript
7
star
67

auth-worker

OAuth2 Service Worker handler
TypeScript
7
star
68

array_validator

Array Validations for ActiveModel
Ruby
7
star
69

eightshift-storybook

Storybook package for Eightshift-Boilerplate
7
star
70

icomcom-react

๐Ÿ’ฌ A React component for handling communication with content in <iframe />
JavaScript
7
star
71

dox-demo

Demo app for dox gem:
HTML
6
star
72

android-localian

Android library that manages your application locale and language across multiple Android API levels.
Kotlin
6
star
73

ios-handbook

Slim
6
star
74

flutter-prince-of-versions

Library used for easier versioning of your applications, allowing you to prompt your users to update the app to the newest version
Dart
6
star
75

learn-react

๐Ÿ‘‹ โš›๏ธ Learn React by implementing your own!
TypeScript
5
star
76

I18n-js

Javascript library for string internationalization.
CoffeeScript
5
star
77

ios-collar

In-app analytics debugging tool
Swift
5
star
78

ngx-form-object

Reactive forms manager
TypeScript
5
star
79

ios-sentinel

Developerโ€™s toolbox for debugging applications
Swift
4
star
80

mobx-keys-store

Keys store for MobX
TypeScript
4
star
81

mysterious-sampler

Swift
4
star
82

rails-infinum-jsonapi_example_app_old

Ruby
4
star
83

phrasing_plus

Phrasing extension for editing images inline
Ruby
4
star
84

eightshift-web-components

Web components library that exposes custom scripts and styles for modern WordPress projects
Svelte
4
star
85

Install-Flutter-Version-Manager-Bitrise

Shell
4
star
86

infinum_setup

Setup script
Ruby
4
star
87

loglevel-filesave

Loglevel plugin for saving logs to the file
JavaScript
4
star
88

eightshift-blocks

Project dedicated to use inside WP Boilerplate and WP Boilerplate Plugin projects via composer to be able to easily setup modern development process for Gutenberg blocks..
PHP
3
star
89

data_sync

Rails plugin for database and file synchronization
Ruby
3
star
90

next-passenger

next.js with passenger proof of concept
Dockerfile
3
star
91

SocketMan

Android WebSocket client app
Java
3
star
92

react-asset-collector

Collect assets from react components so you can do HTTP2 push
JavaScript
3
star
93

rails_log_book

Ruby
3
star
94

mina-secrets

Mina plugin for secrets_cli gem
Ruby
2
star
95

docusaurus-theme

Infinum Docusaurus teme
JavaScript
2
star
96

ngx-nuts-and-bolts

A collection of commonly used pieces of Angular-related code that we use everyday at Infinum.
TypeScript
2
star
97

money_with_date

Extension for the money gem which adds dates to Money objects.
Ruby
2
star
98

blog-android-permissions

Java
2
star
99

JS-RxWorkshop

TypeScript
2
star
100

analytics-handbook

2
star