Functional JSON Parser - Linux Ready

Overview

Alembic

Functional JSON Parser


Swift4 Build Status CodeBeat


CocoaPods Carthage Swift Package Manager


Platform Lincense


Feature

  • Linux Ready
  • Type-safe JSON parsing
  • Functional value transformation
  • Easy to parse nested value
  • Dependency free
  • No defined custom operators

Requirements

  • Swift4.1 or later
  • OS X 10.9 or later
  • iOS 9.0 or later
  • watchOS 2.0 or later
  • tvOS 9.0 or later
  • Linux

Installation

CocoaPods

Add the following to your Podfile:

use_frameworks!

target 'TargetName' do
  pod 'Alembic'
end

Carthage

Add the following to your Cartfile:

github "ra1028/Alembic"

Swift Package Manager

Add the following to your Package.swift:

// swift-tools-version:4.0

let package = Package(
    name: "ProjectName",
    dependencies : [
        .package(url: "https://github.com/ra1028/Alembic.git", .upToNextMajor(from: "3"))
    ]
)

Example

In example, parse the following JSON:

{
    "teams": [
        {
            "name": "Team ra1028",
            "url": "https://github.com/ra1028",
            "members": [
                {
                    "name": "Ryo Aoyama",
                    "age": 23
                },
                {
                    "name": "John Doe",
                    "age": 30
                }
            ]
        }
    ]
}

Make the JSON instance from Any, Data or String type JSON object.

// from `Any` type JSON object
let json = JSON(object)
// from JSON Data
let json = try JSON(data: data)
// from JSON String
let json = try JSON(string: string)

Parse value from JSON:

Parse the values type-safely

let memberName: String = try json.value(for: ["teams", 0, "members", 0, "name"])

Parse nullable value

let missingText: String? = try json.option(for: "missingKey")

Parse value from JSON with transforming:

Transform value using various monadic functions.

let teamUrl: URL = try json.parse(String.self, for: ["teams", 0, "url"])
        .filterMap(URL.init(string:))
        .value()

Transform nullable value if exist

let missingUrl: URL? = try json.parse(String.self, for: "missingKey")
        .filterMap(URL.init(string:))
        .option()

Mapping to model from JSON:

All types conforming to Parsable protocol and it's Array, Dictionary can be parsed.

URL { guard let url = try URL(string: json.value()) else { throw JSON.Error.dataCorrupted(value: json.rawValue, description: "The value was not valid url string.") } return url } } struct Team: Parsable { let name: String let url: URL let members: [Member] static func value(from json: JSON) throws -> Team { return try .init( name: json.value(for: "name"), url: json.value(for: "url"), members: json.value(for: "members") ) } } ">
struct Member: Parsable {
    let name: String
    let age: Int

    static func value(from json: JSON) throws -> Member {
        return try .init(
            name: json.value(for: "name"),
            age: json.value(for: "age")
        )
    }
}

extension URL: Parsable {
    public static func value(from json: JSON) throws -> URL {
        guard let url = try URL(string: json.value()) else {
            throw JSON.Error.dataCorrupted(value: json.rawValue, description: "The value was not valid url string.")
        }
        return url
    }
}

struct Team: Parsable {
    let name: String
    let url: URL
    let members: [Member]

    static func value(from json: JSON) throws -> Team {
        return try .init(
            name: json.value(for: "name"),
            url: json.value(for: "url"),
            members: json.value(for: "members")
        )
    }
}
let team: Team = try json.value(for: ["teams", 0])

Tips

The types conformed to Parsable as default.

JSON
String
Int
UInt
Double
Float
Bool
NSNumber
Int8
UInt8
Int16
UInt16
Int32
UInt32
Int64
UInt64
Decimal
Array where Element: Parsable
Dictionary where Key == String, Value: Parsable
Optional where Wrapped: Parsable

Conform to Parsable with initializer

struct Member: ParseInitializable {
    let name: String
    let age: Int

    init(with json: JSON) throws {
        name = try json.value(for: "name")
        age = try json.value(for: "age")
    }
}

Usage Reference Files

Functional operators for value transforming:

Errors

More Example

See the Test files


Playground

  1. Open Alembic.xcworkspace.
  2. Build the Alembic for Mac.
  3. Open Alembic playground in project navigator.

Contribution

Welcome to fork and submit pull requests!

Before submitting pull request, please ensure you have passed the included tests. If your pull request including new function, please write test cases for it.


License

Alembic is released under the MIT License.


Comments
  • Swift4.1 Support

    Swift4.1 Support

    Breaking changes

    • Array, Dictionary and Optional now conformed Parsable by conditional conformance πŸŽ‰

    Internal

    • Add Script to run test on Linux by Docker
    opened by ra1028 0
  • Feature/v2.1.3

    Feature/v2.1.3

    Improvement

    • Value of JSON and Distillate to be caching
    • Improve the behavior of Path value included in DistillError.typeMismatch

    Breaking

    Rename

    • failedToSerialize -> serializeFailed

    Changes

    • Distillate.filter is now function Distillate.filter()
    opened by ra1028 0
  • Reimplement value/error handler

    Reimplement value/error handler

    Add

    • InsecureDistillate.value(handler: (Value) -> Void)
    • InsecureDistillate.error(handler: (Value) -> Void)
    • SecureDistillate.value(handler: (Value) -> Void)
    opened by ra1028 0
  • Feature/2.1.1

    Feature/2.1.1

    Add

    • Add failedToSerialize(with:) to DistillError
    • Add associated value path: Path to DistillError.typeMismatch

    Breaking

    Change

    • No need to try/catch when intializing JSON from String or Data
    • Argument label to: is now as:

    Rename

    • Rename InitDistillable to Brewable

    Remove

    • Remove function value(handler:) that get value via closure
    • Remove utility functions of Distillate for Collection
    opened by ra1028 0
  • Support Swift3

    Support Swift3

    Add

    • Add function InsecureDistillate.value(): () throws -> Value
    • Add function SecureDistillate.value(): () -> Value
    • Add function Array<Distillable>.distil(j:)
    • Add function Dictionary<Key: StringConvertible, Value: Distillable>.distil(j:)
    • Add protocol InitDistillable

    Breaking

    Obsolete

    • Serialize objects to JSON Data or String
    • DistillateType

    Rename

    • success(_ handler:) to value(_ handler)
    • failure(_ handler:) to error(_ handler)
    • recover() to catch()
    • DistillSubscripted to LazyJSON
    • JSONPath to Path
    • OptionalType to OptionalConvertible
    • JSONPathElement to PathElement

    Change

    • Change the type constraint of distil value functions from distil(Path)(Type) to distil(Path, to: Type)
    • Distillate.filter() is now computed property .filter"
    • JSON became Class object from Struct
    • Enums are now lowercase
    • Some argument labeling rules
    opened by ra1028 0
  • Feature/v1.7.0

    Feature/v1.7.0

    Add

    • Add functions to receive value or error by a data stream
      • .success(handler: Value -> Void)
      • .failure(handler: ErrorType -> Void)

    Minor changes

    • Implements CustomStringConvertible
      • JSON
      • DistillError
      • JSONPath
      • JSONPathElement
    • Change JSONPathElement to enum
    opened by ra1028 0
  • Feature/v1.6.2

    Feature/v1.6.2

    Breaking

    • Change the function name
      • catchReturn -> recover
    • Move the function recover into InsecureDistillate

    Minor changes

    • Separate codes to several files
    opened by ra1028 0
  • Feature/1.6.0

    Feature/1.6.0

    Breaking

    • Changed some struct to class
    • Changed some class names
      • Distillate -> InsecureDistillate
      • DistilError -> DistillError
    • Changed CustomStringConvertible to CustomDebugStringConvertible

    Added

    • Added some functions
      • flatMap(Value -> Optional)
      • flatMapError(ErrorType -> DistillateType)
    • Added some function that create Distillate
      • Distillate.just(Value)
      • Distillate.error(ErrorType)
      • Distillate.filter()
    • Added Distillate as parent of DistillateType classes
    • Added throws annotation to some closures

    Minor changes

    • Change private variable names
    opened by ra1028 0
  • Feature/rename functions

    Feature/rename functions

    Close https://github.com/ra1028/Alembic/issues/3

    Breaking

    • Change function names
      • .catchError(ErrorType -> Value) -> .catchReturn(ErrorType -> Value)

    Minor changes

    • Change private variable names
    • Add lazy evaluation attribute @autoclosure(escaping)
    opened by ra1028 0
  • Feature/refactor

    Feature/refactor

    Breaking

    • Change function names
      • .catchUp(() -> Value) -> .catchError(ErrorType -> Value)
      • .catchUp(Value) -> .catchReturn(Value)
      • .remapEmpty(Value) -> .replaceEmpty(Value)
      • .remapNil(Value.Wrapped) -> .replaceNil(Value.Wrapped)
      • .optional(JSONPath) -> .option(JSONPath)
    • Change struct names
      • Monad -> Distillate
      • SecureMonad -> SecureMonad
    • Remove functions
      • Remove .ensure(Value)
    opened by ra1028 0
  • Double on Linux

    Double on Linux

    Alembic doesn't cast Int value to Double on Linux (MacOS its ok).

    JSONString: {"op":"mcm","id":2,"clk":"AKUBANQBAN0B","pt":1505853621577,"mc":[{"id":"1.133562061","rc":[{"bdatb":[[0,3,214.98]],"id":1221386},{"bdatl":[[0,1.49,68.46]],"id":1221385}]}]}

    Error: typeMismatch(expected: Double, actualValue: 3, path: Path([1]))

    Code:

    struct BDAT: Parsable {
    
        var level: Int
        var price: Double
        var size: Double
        
        static func value(from json: JSON) throws -> BDAT {
            return try .init(
                level: json.value(for: [0]),
                price: json.parse(Double.self, for: [1])
                size: json.value(for: [2])
            )
        }
        
    }
    

    I've already tried: json.parse(Double.self, for: [1]) and json.parse(for: [1])

    SO: Ubuntu 16.04 Swift: 3.1.1

    opened by klevison 1
Releases(3.4.0)
  • 3.4.0(Apr 17, 2018)

  • 3.3.0(Jan 31, 2018)

    Improvements

    Significant performance improvement

    Breaking Changes

    • Rename flatMap to filterMap
    • JSON.Path is now RandomAccessCollection
    • Rename Parsed to Parser
    • Rename ThrowParsed to ThrowParser
    Source code(tar.gz)
    Source code(zip)
  • 3.2.0(Jan 31, 2018)

    #Fix

    • Fix number type parsing on Linux

    #Breaking Changes

    • Add JSON.Error.dataCorrupted
    • Add Parse Decimal type
    • Remove JSON.Error.serializeFailed
    • Rename JSON.Error.custom to JSON.Error.other
    Source code(tar.gz)
    Source code(zip)
  • 3.1.0(Nov 2, 2017)

  • 3.0.0(Sep 19, 2017)

  • 2.1.2(Oct 10, 2016)

    Add

    • InsecureDistillate.value(handler: (Value) -> Void)
    • InsecureDistillate.error(handler: (Value) -> Void)
    • SecureDistillate.value(handler: (Value) -> Void)
    Source code(tar.gz)
    Source code(zip)
  • 2.1.1(Oct 7, 2016)

    Add

    • Add failedToSerialize(with:) to DistillError
    • Add associated value path: Path to DistillError.typeMismatch

    Breaking

    Change

    • No need to try/catch when intializing JSON from String or Data
    • Argument label to: is now as:

    Rename

    • Rename InitDistillable to Brewable

    Remove

    • Remove function value(handler:) that get value via closure
    • Remove utility functions of Distillate for Collection
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Oct 5, 2016)

  • 2.0.0(Sep 26, 2016)

    Support Swift3/Xcode8 πŸŽ‰

    Add

    • Add function InsecureDistillate.value(): () throws -> Value
    • Add function SecureDistillate.value(): () -> Value
    • Add function Array<Distillable>.distil(j:)
    • Add function Dictionary<Key: StringConvertible, Value: Distillable>.distil(j:)
    • Add protocol InitDistillable

    Breaking

    Obsolete

    • Serialize objects to JSON Data or String
    • DistillateType

    Rename

    • success(_ handler:) to value(_ handler)
    • failure(_ handler:) to error(_ handler)
    • recover() to catch()
    • DistillSubscripted to LazyJSON
    • JSONPath to Path
    • OptionalType to OptionalConvertible
    • JSONPathElement to PathElement

    Change

    • Change the type constraint of distil value functions from distil(Path)(Type) to distil(Path, to: Type)
    • Distillate.filter() is now computed property .filter"
    • JSON became Class object from Struct
    • Enums are now lowercase
    • Some argument labeling rules
    Source code(tar.gz)
    Source code(zip)
  • 1.8.1(Sep 3, 2016)

  • 1.8.0(Aug 28, 2016)

  • 1.7.0(Jul 10, 2016)

    Refer https://github.com/ra1028/Alembic/pull/9

    Add

    • Add functions to receive value or error by a data stream
      • .success(handler: Value -> Void)
      • .failure(handler: ErrorType -> Void)

    Minor changes

    • Implements CustomStringConvertible
      • JSON
      • DistillError
      • JSONPath
      • JSONPathElement
    • Change JSONPathElement to enum
    Source code(tar.gz)
    Source code(zip)
  • 1.6.4(Jul 6, 2016)

  • 1.6.3(Jun 28, 2016)

    Refer https://github.com/ra1028/Alembic/pull/7

    Breaking

    • Change the function name
      • catchReturn -> recover
    • Move the function recover into InsecureDistillate

    Minor changes

    • Separate codes to several files
    Source code(tar.gz)
    Source code(zip)
  • 1.6.1(Jun 27, 2016)

    Refer https://github.com/ra1028/Alembic/pull/6

    Added

    • Value extraction by subscript chain

    Breaking

    • Changed some class names
      • DistilSuscripted -> DistillSuscripted
    Source code(tar.gz)
    Source code(zip)
  • 1.6.0(Jun 26, 2016)

    Refer https://github.com/ra1028/Alembic/pull/5

    Breaking

    • Changed some struct to class
    • Changed some class names
      • Distillate -> InsecureDistillate
      • DistilError -> DistillError
    • Changed CustomStringConvertible to CustomDebugStringConvertible

    Added

    • Added some functions
      • flatMap(Value -> Optional)
      • flatMapError(ErrorType -> DistillateType)
    • Added some function that create Distillate
      • Distillate.just(Value)
      • Distillate.error(ErrorType)
      • Distillate.filter()
    • Added Distillate as parent of DistillateType classes
    • Added throws annotation to some closures

    Minor changes

    • Change private variable names
    Source code(tar.gz)
    Source code(zip)
  • 1.5.0(Jun 21, 2016)

    Refer https://github.com/ra1028/Alembic/pull/4

    Breaking

    • Change function names
      • .catchError(ErrorType -> Value) -> .catchReturn(ErrorType -> Value)

    Minor changes

    • Change private variable names
    • Add lazy evaluation attribute @autoclosure(escaping)
    Source code(tar.gz)
    Source code(zip)
  • 1.4.0(May 25, 2016)

    Refer https://github.com/ra1028/Alembic/pull/1

    Breaking

    • Change function names
      • .catchUp(() -> Value) -> .catchError(ErrorType -> Value)
      • .catchUp(Value) -> .catchReturn(Value)
      • .remapEmpty(Value) -> .replaceEmpty(Value)
      • .remapNil(Value.Wrapped) -> .replaceNil(Value.Wrapped)
      • .optional(JSONPath) -> .option(JSONPath)
    • Change struct names
      • Monad -> Distillate
      • SecureMonad -> SecureDistillate
    • Remove functions
      • Remove .ensure(Value)
    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Jun 21, 2016)

Owner
Ryo Aoyama
β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–€β–„β–‘β–‘β–‘β–„β–€β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–„β–ˆβ–€β–ˆβ–ˆβ–ˆβ–€β–ˆβ–„β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–ˆβ–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€β–ˆβ–‘β–‘β–‘ β–‘β–‘β–‘β–ˆβ–‘β–ˆβ–€β–€β–€β–€β–€β–€β–€β–ˆβ–‘β–ˆβ–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–€β–€β–‘β–‘β–‘β–€β–€β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘
Ryo Aoyama
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
This framework implements a strict JSON parser and generator in Objective-C.

SBJson 5 Chunk-based JSON parsing and generation in Objective-C. Overview SBJson's number one feature is stream/chunk-based operation. Feed the parser

null 3.8k Jan 5, 2023
A JSON parser with concise API written in Swift.

A JSON parser with concise API written in Swift Maps JSON attributes to different Swift types with just two methods: map and mapArrayOfObjects. The li

Evgenii Neumerzhitckii 14 Aug 13, 2018
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
A sweet and swifty YAML parser built on LibYAML.

Yams A sweet and swifty YAML parser built on LibYAML. Installation Building Yams requires Xcode 11.x or a Swift 5.1+ toolchain with the Swift Package

JP Simard 930 Jan 4, 2023
JSONFeed parser for swift

JSONFeed Swift parsing for JSON Feed Spec Installation Carthage You can install Carthage with Homebrew using the following command: brew update brew i

Wes 27 Aug 19, 2020
A lightweight CSS parser for parsing and creating CSS stylesheets

SwiftCSSParser A lightweight CSS parser for Swift that uses cssparser (cpp) under the hood. Basic usage Here's a simple code snippet to get you starte

null 9 Jul 20, 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
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
Arrow 🏹 Parse JSON with style

Arrow ?? Parse JSON with style

Fresh 376 Nov 8, 2022
Elevate is a JSON parsing framework that leverages Swift to make parsing simple, reliable and composable

Elevate is a JSON parsing framework that leverages Swift to make parsing simple, reliable and composable. Elevate should no longer be used for

Nike Inc. 611 Oct 23, 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
Freddy - A reusable framework for parsing JSON in Swift.

Why Freddy? Parsing JSON elegantly and safely can be hard, but Freddy is here to help. Freddy is a reusable framework for parsing JSON in Swift. It ha

Big Nerd Ranch 1.1k Jan 1, 2023
[Deprecated] A shiny JSON parsing library in Swift :sparkles: Loved by many from 2015-2021

?? Deprecation Notice ?? Gloss has been deprecated in favor of Swift's Codable framework. The existing Gloss source is not going away, however updates

Harlan Kellaway 1.6k Nov 24, 2022
HandyJSON is a framework written in Swift which to make converting model objects to and from JSON easy on iOS.

HandyJSON To deal with crash on iOS 14 beta4 please try version 5.0.3-beta HandyJSON is a framework written in Swift which to make converting model ob

Alibaba 4.1k Dec 29, 2022