---
title: 'Introducing Argo 1.0: More Power, More Fun'
teaser: Argo 1.0 puts more power in your hands!
tags: news,ios,swift,argo,functional programming
author: Tony DiPasquale
published_on: 2015-05-26
---

[Argo] 1.0 is out! We wanted to slim down [Argo] while maintaining usability
and give it more power, so we sifted through every line and asked "Is this
needed?", "Is there a better way?", and "Is this named properly?". What we're
left with is an all-around better [Argo] that's easier to use and debug.

[Argo]: https://github.com/thoughtbot/Argo

So, what's new?

## Decoded

The biggest change to Argo 1.0 is the introduction of the `Decoded<T>` type.
In previous versions of Argo, we've relied heavily on Swift's Optionals to
represent the result of decoding the JSON into a model. `.None` meant failure
and `.Some(T)` meant success. This worked fine for most cases but broke down if
you wanted more context around why the decoding failed. Users were forced
to always use an `Optional` result and could not take advantage of a more complex
custom type like [`Result`].

[`Result`]: https://github.com/antitypical/Result

We've replaced `Optional` with a `Decoded<T>` type that represents three
possible outcomes of decoding: Success, Type Mismatch, or Missing Key.  Success
is the same as `.Some` was before, representing a successful decoding. The two
new error types allow us to retain a more detailed reason for failure.
`.TypeMismatch` means that the type needed for the model doesn't match the type
in the JSON. `.MissingKey` means that the key requested from the JSON doesn't
exist or is NULL.

We reworked the `JSONDecodable` protocol to have the `decode` function return
the new `Decoded<T>` type, where `T` is the `DecodedType` typealias. Let's take
a look at what decoding a `User` used to look like and what it looks like with
Argo 1.0.

Given a `User` object represented in JSON like this:

```json
{
  "id": 5,
  "name": "Gob",
  "email": "gob@bananastand.com"
}
```

Before Argo 1.0, we would implement the `decode` function like so:

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

  static func decode(j: JSONValue) -> User? {
    return User.create
      <^> j <| "id"
      <*> j <| "name"
      <*> j <| "email"
  }
}
```

Now with Argo 1.0, we slightly modify the `decode` function definition but
everything else is the same:

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

  static func decode(j: JSON) -> Decoded<User> {
    return User.create
      <^> j <| "id"
      <*> j <| "name"
      <*> j <| "email"
  }
}
```

## Global decode

To decode JSON into our `User` model, we used to do this:

```swift
let json: AnyObject? = NSJSONSerialization...
let value: JSONValue? = json.map { JSONValue.parse($0) }
let user: User? = value.flatMap(User.decode)
```

To make this easier with the new `Decoded<T>` type, Argo 1.0 introduces a
global `decode` function that will call `parse` and the model's `decode`
function for you.

```swift
let json: AnyObject? = NSJSONSerialization...
let user: User? = json.flatMap(decode)
```

You can still choose to ignore the `Decoded<T>` type and its error info by
typing the result of the expression as a `User?` as we did above. If you would
like to keep the error context, then type the result as `Decoded<User>` like
so:

```swift
let json: AnyObject? = NSJSONSerialization...
let user: Decoded<User> = json.flatMap(decode)
```

With a `Decoded<User>` you can use a `switch` statement to handle the different
success or error possibilities. You can also just print the value using
`println` and see the error message in the console.

## Some Renaming

We've also shortened a few names. `JSONDecodable` is now just `Decodable` and
`JSONValue` is just `JSON`.

## What does it all mean?

The `Decoded<T>` type allows you to retain detailed error information of
decoding failures. The global `decode` function allows you to ignore the new
`Decoded<T>` type if you choose or use it to handle decoding failures. More
interestingly, both of these additions pave the way for you to implement your
own return type from a decode. For instance, you can overload the global
`decode` function to return a `Result<User>`. This puts power in the user's
hands to customize Argo to return values that stay consistent with the rest of
the code base.

## Go Forth and Decode

Thanks to everyone who helped get Argo to 1.0 through [issues] and [PRs]. We
think Argo makes decoding objects from JSON easy and efficient and we're glad
you think so too! Keep your contributions coming and let's `decode` for a
better tomorrow together!

[issues]: https://github.com/thoughtbot/Argo/issues
[PRs]: https://github.com/thoughtbot/Argo/pulls
