---
title: Real World JSON Parsing with Swift
teaser:
tags: ios,swift
author: Tony DiPasquale
published_on: 2014-09-18
---

[Last time], we looked at using concepts from Functional Programming and
Generics to parse <abbr title="JavaScript Object Notation">JSON</abbr> received
from a server into a `User` model. The final result of the <abbr
title="JavaScript Object Notation">JSON</abbr> parsing looked like this:

[Last time]: https://thoughtbot.com/blog/efficient-json-in-swift-with-functional-concepts-and-generics

```swift
struct User: JSONDecodable {
  let id: Int
  let name: String
  let email: String

  static func create(id: Int)(name: String)(email: String) -> User {
    return User(id: id, name: name, email: email)
  }

  static func decode(json: JSON) -> User? {
    return _JSONObject(json) >>> { d in
      User.create <^>
        d["id"]    >>> _JSONInt    <*>
        d["name"]  >>> _JSONString <*>
        d["email"] >>> _JSONString
    }
  }
}
```

This is great, but in the real world the objects we get back from an API will
not always be perfect. Sometimes an object will have only a few important keys
and the rest can be retrieved later.

For example, when we fetch the current user we want all of the user's info, but
when we fetch a user by their `id` we don't want the email for security
reasons. To hide the email, the server will only respond with the `id` and
`name` for all users that are not the current user. To reuse the same `User`
object, it's more realistic to describe a `User` like this:

```swift
struct User {
  let id: Int
  let name: String
  let email: String?
}
```

You can see that the user's email property is now an optional `String`. If you
remember, the `<^>` (fmap) and `<*>` (apply) operators ensure that we only get
our `User` struct if the <abbr title="JavaScript Object Notation">JSON</abbr>
contains all the keys; otherwise, we get `.None`. If the email returned from the
server is `.None` or `nil`, the decode function will fail. We can fix this by
adding a `pure` function.

`pure` is a function that takes a value without context and puts that value into
a minimal context. Swift optionals are values in a "there-or-not" context;
therefore, `pure` means `.Some(value)`. The implementation is simply:

```swift
func pure<A>(a: A) -> A? {
  return .Some(a)
}
```

Now we can use it to parse a `User` who may or may not have an email:

```swift
struct User: JSONDecodable {
  let id: Int
  let name: String
  let email: String?

  static func create(id: Int)(name: String)(email: String?) -> User {
    return User(id: id, name: name, email: email)
  }

  static func decode(json: JSON) -> User? {
    return _JSONObject(json) >>> { d in
      User.create <^>
             d["id"]          >>> _JSONInt     <*>
             d["name"]        >>> _JSONString  <*>
        pure(d["email"]       >>> _JSONString)
    }
  }
}
```

Without `pure`, `d["email"] >>> _JSONString` would return `.None` if there were
no `"email"` key within `d`. `<*>` looks for an optional and when it sees
`.None`, it would stop creating the `User` and return `.None` for the whole
function. However, when we call `pure` on the result, if the email was not
present we'll get `.Some(.None)` and `<*>` will accept and unwrap the optional
then pass `.None` into the initializer.

## More Type Inference

The above code works great, but there is still a lot of syntax we need to write
in order to create our `User`. We can use Swift's type inference to refactor
this code.

We have been using a few functions to parse a <abbr title="JavaScript Object
Notation">JSON</abbr> `AnyObject` type into the type that the `create` function
needs. With type inference, we can use the definition of the `create` function
to tell the JSON parsing function what type we're looking for. Currently,
`_JSONInt` and `_JSONString` look like this:

```swift
func _JSONInt(json: JSON) -> Int? {
  return json as? Int
}

func _JSONString(json: JSON) -> String? {
  return json as? String
}
```

It's easy to see that these functions are very similar, in fact, they only
differ by the type. Sounds like a use for Generics.

```swift
func _JSONParse<A>(json: JSON) -> A? {
  return json as? A
}
```

Now we can use `_JSONParse` in our `decode` function instead of needing a
specific parsing function for every <abbr title="JavaScript Object
Notation">JSON</abbr> type.

```swift
struct User: JSONDecodable {
  let id: Int
  let name: String
  let email: String?

  static func create(id: Int)(name: String)(email: String?) -> User {
    return User(id: id, name: name, email: email)
  }

  static func decode(json: JSON) -> User? {
    return _JSONParse(json) >>> { (d: JSONObject) in
      User.create <^>
             d["id"]          >>> _JSONParse  <*>
             d["name"]        >>> _JSONParse  <*>
        pure(d["email"]       >>> _JSONParse)
    }
  }
}
```

This works because `User.create` is a function that takes an `Int` and it is
being applied to `d["id"] >>> _JSONParse`. The compiler will infer that the
generic type within `_JSONParse` has to be an `Int`.

You'll notice that in order to use `_JSONParse` in place of `_JSONObject` we
had to cast `d` to a `JSONObject` so that `_JSONParse` can infer the type.

Our decoding function is getting better but there is still a lot of duplication.
It would be nice to eliminate all the calls to `_JSONParse`. These lines are all
similar except for the key being used to extract the <abbr title="JavaScript
Object Notation">JSON</abbr> value. We can abstract this code to save on
duplication. While we do that we can make a similar function to abstract any
value that also needs to call `pure`.

```swift
func extract<A>(json: JSONObject, key: String) -> A? {
  return json[key] >>> _JSONParse
}

func extractPure<A>(json: JSONObject, key: String) -> A?? {
  return pure(json[key] >>> _JSONParse)
}
```

And now we have:

```swift
struct User: JSONDecodable {
  let id: Int
  let name: String
  let email: String?

  static func create(id: Int)(name: String)(email: String?) -> User {
    return User(id: id, name: name, email: email)
  }

  static func decode(json: JSON) -> User? {
    return _JSONParse(json) >>> { d in
      User.create <^>
        extract(d, "id")        <*>
        extract(d, "name")      <*>
        extractPure(d, "email")
    }
  }
}
```

Now that we have the `extract` function that takes a `JSONObject` as its first
parameter, we can remove the type cast on `d` because it is inferred to be a
`JSONObject` by passing it into `extract`.

`extract` and `extractPure` are a lot to type every time and it could be more
readable if it were infix. Let's create a couple custom operators to do the job
for us. We'll use `<|` and `<|?`, which are inspired from Haskell's popular
JSON parsing library, [Aeson]. Aeson uses `.:` and `.:?`, but those are
[illegal operators in Swift], so we'll use the `<|` version instead.

[Aeson]: https://hackage.haskell.org/package/aeson
[illegal operators in Swift]: http://www.openradar.me/radar?id=6061088852410368

NOTE: `?` is illegal to use in a custom operator in Swift 1.0. This is solved
in Swift 1.1 which is currently in Beta 2. You can use `<|*` as an alternative
to `<|?` for now.

```swift
infix operator <|  { associativity left precedence 150 }
infix operator <|? { associativity left precedence 150 }

func <|<A>(json: JSONObject, key: String) -> A? {
  return json[key] >>> _JSONParse
}

func <|?<A>(json: JSONObject, key: String) -> A?? {
  return pure(json[key] >>> _JSONParse)
}
```

Now we can use these operators in out `User` decoding. We'll also move the
operators to the front of the line for better style.

```swift
struct User: JSONDecodable {
  let id: Int
  let name: String
  let email: String?

  static func create(id: Int)(name: String)(email: String?) -> User {
    return User(id: id, name: name, email: email)
  }

  static func decode(json: JSON) -> User? {
    return _JSONParse(json) >>> { d in
      User.create
        <^> d <|  "id"
        <*> d <|  "name"
        <*> d <|? "email"
    }
  }
}
```

Wow! Using Generics and relying on Swift's type inference can really reduce the
amount of code we have to write. What's really interesting is how close we can
get to a purely functional programming language like Haskell. Using Aeson in
Haskell, decoding a User would look like this:

```haskell
instance FromJSON User where
  parseJSON (Object o) = User
    <$> o .:  "id"
    <*> o .:  "name"
    <*> o .:? "email"
  parseJSON _ = mzero
```

## Conclusion

We've come a long way since the [first post]. Let's bring back the old way
and look how it compares to what we can do now excluding the `NSData` to
`AnyObject?` conversion.

[first post]: https://thoughtbot.com/blog/efficient-json-in-swift-with-functional-concepts-and-generics

### Original Method

```swift
extension User {
  static func decode(json: AnyObject) -> User? {
    if let jsonObject = json as? [String:AnyObject] {
      if let id = jsonObject["id"] as AnyObject? as? Int {
        if let name = jsonObject["name"] as AnyObject? as? String {
          if let email = jsonObject["email"] as AnyObject? {
            return User(id: id, name: name, email: email as? String)
          }
        }
      }
    }
    return .None
  }
}
```

### Improved Method

```swift
extension User: JSONDecodable {
  static func create(id: Int)(name: String)(email: String?) -> User {
    return User(id: id, name: name, email: email)
  }

  static func decode(json: JSON) -> User? {
    return _JSONParse(json) >>> { d in
      User.create
        <^> d <|  "id"
        <*> d <|  "name"
        <*> d <|? "email"
    }
  }
}
```

The related code can be found on [GitHub].

[GitHub]: https://github.com/thoughtbot/FunctionalJSON-swift
