Jay - Pure-Swift JSON parser & formatter. Fully streamable input and output. Linux & OS X ready.

Related tags

JSON Jay
Overview

Jay

Build Status Latest Release Platforms Package Managers

Pure-Swift JSON parser & formatter. Fully streamable input and output. Linux & OS X ready. Replacement for NSJSONSerialization.

Jay conforms to the following specifications:

For extra convenience functions when working with the JSON enum, check out Jay-Extras.

Why?

We all use JSON. Especially when writing server-side Swift that needs to run on Linux. #0dependencies

This is my take on how a JSON parser should work. This is not another JSON mapping utility library. This is an actual JSON parser and formatter. Check out the code, it was fun to write 😇

Features

  • Parsing: data -> JSON object
  • Formatting: JSON object -> data
  • Pretty printing
  • Streaming input and output, low memory footprint

Usage

Parsing from data (deserialization)

do {
	//get data from disk/network
	let data: [UInt8] = ...

	//ask Jay to parse your data
	let json = try Jay().jsonFromData(data) // JSON
	//or
	let json = try Jay().anyJsonFromData(data) // [String: Any] or [Any]

	//if it doesn't throw an error, all went well
	if let tasks = json.dictionary?["today"]?.array {
	    //you have a dictionary root object, with an array under the key "today"
	    print(tasks) //["laundry", "cook dinner for gf"]
	} 
} catch {
	print("Parsing error: \(error)")
}

Formatting into data (serialization)

do {
	//get a json object (works for both [String: Any] and typesafe versions - JSON)

	//ask Jay to generate data
	let anyContainer = ... // [String: Any] or [Any]
	let data = try Jay(formatting: .prettified).dataFromJson(any: json) // [UInt8]
	//or
	let json: JSON = ... // JSON
	let data = try Jay(formatting: .prettified).dataFromJson(json: json) // [UInt8]

	//send data over network, save to disk
} catch {
	print("Formatting error: \(error)")
}

Installation

Swift Package Manager

.Package(url: "https://github.com/czechboy0/Jay.git", majorVersion: 1)

💙 Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

💝 Contributing

Please create an issue with a description of your problem or open a pull request with a fix.

✌️ License

MIT

👽 Author

Honza Dvorsky - http://honzadvorsky.com, @czechboy0

Comments
  • Make to compile with new Swift 3 API

    Make to compile with new Swift 3 API

    ~~There is one caveat, in Sources/Jay/Formatter.swift in formatObject(object:), there seems to be an upstream issue (or something I don't understand), because I could not eliminate an "ambiguous use of member sort" on the line let pairs = object.sort(isOrderedBefore: { (a, b) -> Bool in a.0 <= b.0 }). Even adding the isOrderedBefore label didn't let it compile. So at the moment, the sorting is just commented out.~~ Fixed in a later commit.

    opened by rothomp3 11
  • Incorrect String->Int map detection

    Incorrect String->Int map detection

    When I run the following code:

    let value = ["foo": 42]
    print(value)
    if let data = try? Jay().dataFromJson(any: value) {
    print(String(bytes: data, encoding: String.Encoding.utf8))
    }
    

    it outputs

    ["foo": 42]
    Optional("{\"foo\":true}")
    

    Is it expected that Jay interprets the number as a boolean?

    opened by remko 8
  • update travis and version for 3.0 release

    update travis and version for 3.0 release

    Hey Dan,

    Thanks for taking over for Honza 👍 , looking forward to parsing some more JSON.

    This PR is because 3.0 is officially out on Linux, and we're looking to stabilize our dependencies w/ this 1.0 as soon as we can.

    Thanks,

    Logan

    opened by loganwright 5
  • remove examples

    remove examples

    Example projects clutter the swift build output, increase the duration of build times, and complicate integration with other platforms like iOS.

    We've asked the SwiftPM team for ways to make examples "public" or "private", but it looks like such features won't be available for the foreseeable future.

    Until then, those wanting to test out the examples can simply clone Jay and uncomment the Target in the Package.

    opened by tanner0101 3
  • Purpose of Jay struct

    Purpose of Jay struct

    It seems that the Jay struct should have static functions instead of member functions, since the member functions only create instances of NativeParser and NativeTypeConverter.

    opened by a2 2
  • Added support for JSON comments

    Added support for JSON comments

    Fixes #43. /cc @tannernelson

    Funny thing, the easiest way to do it was to treat comments as a new type of token that we're trying to parse. This means I actually pull all those comments out before throwing them away. Means that if we found a nice API to emit found comments, that would be very easy to do. (But I don't think that's really useful, just a fun fact)

    opened by czechboy0 1
  • Add support for JSON comments

    Add support for JSON comments

    JSON comments are a thing apparently. Add support for ignoring them during parsing.

    @tannernelson can you please provide specific rules for where and when they can appear?

    opened by czechboy0 1
  • Added header documentation to (most) public interfaces

    Added header documentation to (most) public interfaces

    See #25

    Hey @czechboy0, I had a go at adding header docs to Jay. Please take a look.

    Note that not all public interfaces have header docs at the moment; please let me know what / how I can change them for the better. 👍

    opened by BasThomas 1
  • Can't parse exponents that starts with zero

    Can't parse exponents that starts with zero

    The API that I consume (sinatra app) has numbers with exponent like this one: 6.8e-05. I don't think this is required by the current RFC4627 spec but I think this will make Jay (and Vapor) more compatible with other API services in the wild.

    // this will fail
    let data = "{ \"number\" : 6.8e-05 }".chars()
    _ = try Jay().jsonFromData(data)
    

    I can confirm that JS console and JSONSerialization support it.

    opened by ikhsan 0
  • Incorrect parsing of Double values if the fraction part starts with zeroes

    Incorrect parsing of Double values if the fraction part starts with zeroes

    Consider the following JSON with three double values: [0.608, 0.0608, 0.00608]. When parsed with Jay, the resulting array contains 0.608 three times, so the scale is completely lost.

    In other words:

    import Jay
    
    let testData = Array("[0.608, 0.0608, 0.00608]".utf8)
    
    let jay = Jay()
    let json = try jay.anyJsonFromData(testData)
    print(json) // [0.60799999999999998, 0.60799999999999998, 0.60799999999999998]
    

    After some investigation, the culprit is NumberParser.swift:202, where the collected fractional digits are naively converted to an integer. For example when parsing the third number, the digs array ["0", "0", "6", "0", "8"] becomes 608, losing the two initial zeroes.

    opened by vzsg 0
  • Also escape other whitespace control characters

    Also escape other whitespace control characters

    Currently we don't escape all characters in the 0x00 to 0x1F range, as the spec describes:

    All Unicode characters may be placed within the quotation marks except for the characters that must be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F).

    We should escape them all, to properly conform.

    opened by czechboy0 0
  • dataFromJson() Int 0,1 exchange Bool

    dataFromJson() Int 0,1 exchange Bool

    Use Vapor 1.0.3 contains Jay. Xcode 8.0.

    .Package(url: "https://github.com/DanToml/Jay.git", majorVersion: 1)

    func dictionaryToJayType(_ maybeDictionary: Any) throws -> JSON? {
    
        let mirror = Mirror(reflecting: maybeDictionary)
        let childrenValues = mirror.children.map { $0.value }
    
        var obj = [String: JSON]()
        for i in childrenValues {
    
            let childMirror = Mirror(reflecting: i)
            let children = childMirror.children
            if childMirror.displayStyle == .tuple && children.count == 2 {
                let it = children.makeIterator()
                let maybeKey = it.next()!.value
                guard let key = maybeKey as? String else {
                    throw JayError.keyIsNotString(maybeKey)
                }
                let value = it.next()!.value
                obj[key] = try self.toJayType(value) // Int 1 -> .boolean(true)
            } else {
                throw JayError.unsupportedType(childMirror)
            }
        }
        return .object(obj)
    }
    
    opened by iq3addLi 0
  • Cannot parse JSON with integer values bigger than Int.max

    Cannot parse JSON with integer values bigger than Int.max

    I cannot parse a JSON object which has an integer value bigger than Int.max.

    The error happens when I call try Jay(parsing: parsing).jsonFromData(serialized) where serialized is an array of UInt8 and represents a valid JSON object. Jay is failing in line 156 of NumberParser.swift:

    //look for other number-allowed chars in this context
    //although int-section terminating
    if intTerm.contains(reader.curr()) {
        //gracefully end this section
        let intString = try digs.string()
        let int = Int(intString)! // FAILING LINE. intString = "9223372036854776000"    
        return int
    }
    

    The error is fatal error: unexpectedly found nil while unwrapping an Optional value. The stack trace looks like:

    Current stack trace:
    0    libswiftCore.dylib                 0x0000000100f03580 swift_reportError + 132
    1    libswiftCore.dylib                 0x0000000100f20850 _swift_stdlib_reportFatalError + 61
    2    libswiftCore.dylib                 0x0000000100d1c550 specialized specialized StaticString.withUTF8Buffer<A> ((UnsafeBufferPointer<UInt8>) -> A) -> A + 355
    3    libswiftCore.dylib                 0x0000000100e94600 partial apply for (_fatalErrorMessage(StaticString, StaticString, StaticString, UInt, flags : UInt32) -> Never).(closure #2) + 109
    4    libswiftCore.dylib                 0x0000000100d1c550 specialized specialized StaticString.withUTF8Buffer<A> ((UnsafeBufferPointer<UInt8>) -> A) -> A + 355
    5    libswiftCore.dylib                 0x0000000100e4f970 specialized _fatalErrorMessage(StaticString, StaticString, StaticString, UInt, flags : UInt32) -> Never + 96
    6    Jay                                0x000000010081b170 NumberParser.parseInt<A where ...> (A) throws -> Int + 2140
    7    Jay                                0x0000000100819f10 NumberParser.parse<A where ...> (with : A) throws -> JSON + 898
    8    Jay                                0x0000000100827030 ValueParser.parse<A where ...> (with : A) throws -> JSON + 1653
    9    Jay                                0x000000010081d270 ObjectParser.parse<A where ...> (with : A) throws -> JSON + 2269
    10   Jay                                0x0000000100827030 ValueParser.parse<A where ...> (with : A) throws -> JSON + 587
    11   Jay                                0x000000010081d270 ObjectParser.parse<A where ...> (with : A) throws -> JSON + 2269
    12   Jay                                0x0000000100827030 ValueParser.parse<A where ...> (with : A) throws -> JSON + 587
    13   Jay                                0x000000010081d270 ObjectParser.parse<A where ...> (with : A) throws -> JSON + 2269
    14   Jay                                0x0000000100827030 ValueParser.parse<A where ...> (with : A) throws -> JSON + 587
    15   Jay                                0x000000010081d270 ObjectParser.parse<A where ...> (with : A) throws -> JSON + 2269
    16   Jay                                0x0000000100827030 ValueParser.parse<A where ...> (with : A) throws -> JSON + 587
    17   Jay                                0x00000001007fdf10 ArrayParser.parse<A where ...> (with : A) throws -> JSON + 766
    18   Jay                                0x0000000100827030 ValueParser.parse<A where ...> (with : A) throws -> JSON + 1112
    19   Jay                                0x000000010081d270 ObjectParser.parse<A where ...> (with : A) throws -> JSON + 2269
    20   Jay                                0x0000000100822be0 RootParser.parse<A where ...> (with : A) throws -> JSON + 362
    21   Jay                                0x0000000100820920 Parser.parseJsonFromReader<A where ...> (A) throws -> JSON + 132
    22   Jay                                0x0000000100820d80 Parser.parseJsonFromData([UInt8]) throws -> JSON + 118
    23   Jay                                0x0000000100811950 Jay.jsonFromData([UInt8]) throws -> JSON + 95
    

    I'm using Jay version 1.0.0.

    opened by m-revetria 1
  • Offer a String API

    Offer a String API

    Am I correct that the only JSON serialization format supported right now is raw data? I'm guessing this is because this is what JSONSerialization offers?

    In practice, I find it annoying to have to work with raw data, as I always work with Strings when using JSON, and let later stages care about which encoding to put it on the wire. As far as I understand, this means I have to always run this through String:validatingUTF8 (and know that the raw data Jay returns is UTF-8, which is undocumented at the moment), and force-unpack the optional (which I can be 100% sure is valid utf-8 anyway); vice versa, it means I have to call .utf8 every time I want to parse something with Jay (which is slightly less annoying than the former).

    Wouldn't it be good to offer an API that parses and serializes to Strings?

    Also, the fact that the API only takes raw bytes means you have to document which encoding it is in and which encoding it outputs. JSONSerialization takes any encoding, Jay only seems to take UTF-8, (see #54 ).

    opened by remko 7
  • UTF-16 unsupported

    UTF-16 unsupported

    When calling jsonFromData with an array of UTF-16-encoded bytes, Jay throws unimplemented.

    The RFC recommends to determine the encoding by looking at the initial bytes (section 3).

    I don't really want UTF-16, but if the API offers (only) a raw bytes interface, I would expect it to take any encoding like JSONSerialization does.

    opened by remko 4
  • Performance comparisons?

    Performance comparisons?

    I'm curious how parsing performance compares to other JSON parsers like

    • NSJSONSerialization
    • yajl
    • jsonsl

    It would be nice to see some timing results on realistic JSON documents.

    opened by snej 3
Releases(1.0.1)
Owner
Danielle
Kubernetes maintainer, formerly CocoaPods, Fastlane, Nomad @HashiCorp, Build Platform @CircleCI
Danielle
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
🪞 Formatter JSON delightfully.

SwiftJSONFormatter ?? Formatter JSON delightfully. Highlights Beautify and minify JSON strings. Keep dictionary key order stable. Work with invalid JS

Zihua Li 8 Dec 19, 2022
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
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
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
PMJSON provides a pure-Swift strongly-typed JSON encoder/decoder

Now Archived and Forked PMJSON will not be maintained in this repository going forward. Please use, create issues on, and make PRs to the fork of PMJS

Postmates Inc. 364 Sep 28, 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
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
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
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
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
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
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
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
ObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects to and from JSON.

ObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects (classes and structs) to and from J

Tristan Himmelman 9k Jan 2, 2023
YamlSwift - Load YAML and JSON documents using Swift

YamlSwift parses a string of YAML document(s) (or a JSON document) and returns a Yaml enum value representing that string.

Behrang Norouzinia 384 Nov 11, 2022