Latest 0.3
Homepage https://github.com/robertpalmer/JSONMapper
License MIT
Platforms ios 8.0
Authors

JSONMapper is a simple way deal with json data in swift.

Requirements

  • Swift 2
  • Xcode 7 beta 6

Playground

Open the ‘Playground/Playground.xcworkspace’ file in Xcode to try JSONMapper.

Example:

import Foundation
import JSONMapper

let json = "["
+    "{"
+    ""id": 1296269,"
+    ""owner": {"
+        ""login": "octocat","
+        ""id": 1,"
+        ""avatar_url": "https://github.com/images/error/octocat_happy.gif","
+        ""type": "User","
+        ""site_admin": false"
+    "},"
+    ""name": "Hello-World","
+    ""private": false,"
+    ""url": "https://api.github.com/repos/octocat/Hello-World","
+ "}]"

let data = json.dataUsingEncoding(NSUTF8StringEncoding)
let reposObject = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions(rawValue: 0))

let repos = Decode(content: reposObject)

Access values

var name: String
name = try! repos[0]["name"].decode() // Hello-World
name = try! repos[0]["name"]~         // Hello-World

Values can be accessed through the subscript methods. The return type of the subscript is a DecodeValue. The decode() method or the ‘~’ postfix oparator decode the the value to the inferred type.

let ownerId: Int = try! repos[0]["owner"]["id"]~  // 1
let privateRepo: Bool = try! repos[0]["private"]~ // false
let urlString: String = try! repos[0]["url"]~     // https://api.github.com/repos/octocat/Hello-World

The return type is inferred from the type of the variable it is assigned to. The type must implement the Decodable protocol.
JSONMapper implements the protocol for String, Int, Bool and Float.

Structs, classes and enum types can be extended to be ‘Decodable’.

Class from the Foundation.framework:

extension NSURL: Decodable {
    public static func decode(value: DecodeValue) throws -> Self? {
        return self.init(string: try value.decode())
    }
}

let url: NSURL = try! repos[0]["url"]~ // NSURL(string: https://api.github.com/repos/octocat/Hello-World)

Enums

enum OwnerType: String {
    case User = "User"
    case Admin = "Admin"
}

extension OwnerType: Decodable {
    static func decode(value: DecodeValue) throws -> OwnerType? {
        return OwnerType(rawValue: try value.decode())
    }
}

let type: OwnerType = try! repos[0]["owner"]["type"]~

Structs

struct Owner {
    let login: String
    let id: Int
    let avatarURL: NSURL
    let type: OwnerType
    let siteAdmin: Bool
}

extension Owner: Decodable {
    static func decode(value: DecodeValue) throws -> Owner? {

        return try Owner(login: value["login"]~,
            id: value["id"]~,
            avatarURL: value["avatar_url"]~,
            type: value["type"]~,
            siteAdmin: value["site_admin"]~)
    }
}

struct Repo {
    let id: Int
    let owner: Owner
    let name: String
    let isPrivate: Bool
    let url: NSURL
}

extension Repo: Decodable {
    static func decode(value: DecodeValue) throws -> Repo? {

        return try Repo(id: value["id"]~,
                     owner: value["owner"]~,
                      name: value["name"]~,
                 isPrivate: value["private"]~,
                       url: value["url"]~)
    }
}

let r: [Repo] = try! repos~

print(r[0].name) // Hello-World
print(r[0].owner.avatarURL) // https://github.com/images/error/octocat_happy.gif

Errors

When the expected return type is not a ‘Decodable’ the code will not compile.

// will not compile
let s: UIView = Decode(content: "a string").decode()

When a value can not be decoded to a specific type or, the decode method throws an error.

let s: String = try repos[0]["private"]~
// Expected 'String' for key '[0][private]', got '__NSCFBoolean'.

let s: String = try repos["name"]~
// Expected 'Dictionary<String, AnyObject>' for key '', got '__NSCFArray'.

let s: String = try repos[0][0]~
// Expected 'Array<AnyObject>' for key '[0]', got '__NSCFDictionary'.

Also when a key can not be found in the dictionary or array, the decode methods will throw an error.

let s: String = try repos[0]["not_defined"]~
// Value for '[0][not_defined]' not found.

let s: String = try repos[1]~
// Value for '[1]' not found.

When the inferred return type is an optional, the error is ignored and the return value is nil.

let s: String? = try repos[1]~ // s == nil

If the inferred type is an optional, but an error should be thrown nevertheless, the return type can be casted to a non optional.

let s: String? = try repos[1]~ as String
// Value for '[1]' not found.

On the other hand, if the inferred type is not an optional, but may fail, it is possible to provide a default value using the ?? operator.

let s2: String = try repos[1]~ ?? "default"       // s2 == "default"

If the return type is an array, the values that cannot be decoded are omitted from the array.

let arrayValue = Decode(content: [ 1, 2, "3", 4])

let intArray: [Int] = try! arrayValue~             // [1, 2, 4]
let stringArray: [String] = try! arrayValue~       // ["3"]
let ownerTypeArray: [OwnerType] = try! arrayValue~ // []

Installation

Carthage

github "robertpalmer/JSONMapper"

Cocoapods

platform :ios, '8.0'
use_frameworks!

pod 'JSONMapper'

Some other json libraries and inspiration:

Latest podspec

{
    "name": "JSONMapper",
    "version": "0.3",
    "summary": "JSONMapper is a simple way deal with json data in swift.",
    "description": "JSONMapper is a simple way deal with json data in swift. It requires Xcode 7 beta 6 or newer.",
    "homepage": "https://github.com/robertpalmer/JSONMapper",
    "license": "MIT",
    "authors": {
        "Robert Palmer": "[email protected]"
    },
    "platforms": {
        "ios": "8.0"
    },
    "source": {
        "git": "https://github.com/robertpalmer/JSONMapper.git",
        "tag": "0.3"
    },
    "source_files": [
        "JSONMapper",
        "JSONMapper/**/*.{h,m}"
    ],
    "exclude_files": "JSONMapperTests"
}

Pin It on Pinterest

Share This