harlan kellaway's blog // Swift JSON Parsing by Example - ft. Argo, JSONJoy, ObjectMapper, and SwiftyJSON

Published 07-05-2015

Introduction

Since Swift landed on the scene roughly a year ago, a number of libraries have cropped up that help us developers with a central task: parsing JSON into application models. In this post, I’m going to explore how a few of the frontrunners are actually used.

This post is meant to be singly practical and will not delve into opinion or theory as to why one library would be used instead of another. For another practical look at JSON parsers plus some valuable musings, I highly recommend reading Swift JSON Shoot-Out by Sam Davies.

Libraries

The libraries I’ll be exploring are:

Examples will demonstrate how each library handles: simple model creation, JSON to model translation, transforming values during translation, and translating nested models. These examples are not exhaustive of what each library is capable of.

[I’d be remiss if I didn’t mention that, since first publishing this post, I was inspired to write my own JSON parsing library, Gloss. Read more about that here.]

JSON

JSON will be retrieved from the Github API using Alamofire for networking. The JSON retrieved is the representation of the repo for this demo: https://api.github.com/repos/hkellaway/swift-json-comparison

The models present in the demo JSON are Repo and RepoOwner. Despite having many more attributes in the actual JSON, our Repo model will simply have have an id, name, description, url, and Owner. A RepoOwner will have an id and a username.

A simplified version of the JSON we’re using would look as such:

Code

You can explore the code in this post yourself by heading over to: https://github.com/hkellaway/swift-json-comparison

This project uses Cocoapods as a dependency manager with the following pods and versions:

[Note: Pod versions were updated since first being pusblished to make the examples Swift 2.0 compatible - thanks @dearprakash]!

Let’s Explore

Argo

A simple model

The RepoOwner model:

Models are characterized by:

A more complex model

The Repo model:

Property transformers

To translate the url property to an NSURL, we use a transformer function we wrote ourselves, urlFromString(_:), in the create(_:) function.

Nested objects

Repo has a nested object - owner, which is a RepoOwner object. Given RepoOwner is also an Argo model, using it as a property incurs no additional work.

Translation from JSON

Making a network call and translating the resulting NSData into our desired Repo model takes the following form:

Result:

repoId: 38541958
name: swift-json-comparison
description: Optional(“Comparison of Swift JSON libraries”)
URL: https://github.com/hkellaway/swift-json-comparison
owner: ownerId: 5456481; username: hkellaway

Translation is characterized by:


JSONJoy

A simple model

The RepoOwner model:

Models are characterized by:

A more complex model

The Repo model:

Property transformers

To translate the url property to an NSURL, we create an extension on JSONDecoder and define the transformer function urlFromString(_:); this function is used inside init(_:) to transform the desired value.

Nested objects

Repo has a nested object - owner, which is a RepoOwner. This model is translated in the init function by initializing a RepoOwner object with the corresponding decoder: owner = RepoOwnerJSONJoy(decoder[“owner”]). RepoOwner must also be a JSONJoy model.

Translation from JSON

Making a network call and translating the resulting NSData into our desired Repo model takes the following form:

Result:

repoId: 38541958
name: swift-json-comparison
description: Optional(“Comparison of Swift JSON libraries”)
URL: https://github.com/hkellaway/swift-json-comparison
owner: ownerId: 5456481; username: hkellaway

Translation is characterized by:


ObjectMapper

A simple model

The RepoOwner model:

Models are characterized by:

A more complex model

The Repo model:

Property transformers

To translate the url property to an NSURL, we define that mapping with a tuple that takes in a TransformType class as its second argument: url <- (map[“html_url”], URLTransform()). The URLTransform() class is included with ObjectMapper - other custom transformers can be made by creating classes that conform to the TransformType protocol.

Nested objects

Repo has a nested object - owner, which is a RepoOwner. Given RepoOwner is also an ObjectMapper model, using it as a property incurs no additional work.

Translation from JSON

Making a network call and translating the resulting NSData into our desired Repo model takes the following form:

Result:

repoId: Optional(38541958)
name: Optional(“swift-json-comparison”)
description: Optional(“Comparison of Swift JSON libraries”))
URL: Optional(https://github.com/hkellaway/swift-json-comparison)
owner: Optional(ownerId: Optional(5456481); username: Optional(“hkellaway”))

Translation is characterized by:


SwiftyJSON

A simple model

The RepoOwner model:

Models are characterized by:

A more complex model

The Repo model:

Property transformers

Property transformation is not handled in the model.

Nested objects

Nested objects are not handled in the model.

Translation from JSON

Making a network call and translating the resulting NSData into our desired Repo model takes the following form:

Result:

repoId: 38541958
name: swift-json-comparison
description: Optional(“Comparison of Swift JSON libraries”)
URL: https://github.com/hkellaway/swift-json-comparison
owner: ownerId: 5456481; name: hkellaway

Translation is characterized by:

Conclusion

Each of the libraries presented here takes a different approach to how models should be set up and how JSON can be translated into those model objects.

While this post didn’t delve into theorization on which might be better than the other, I certainly hope it helps when it comes time to evaluate such libraries for your next project. Again, you can check out the code seen in this post in action here: https://github.com/hkellaway/swift-json-comparison

Happy coding!



EDIT: Content added 08/16/2015 mentioning my own JSON parsing library, Gloss
EDIT: Content added 11/21/2015 to mention example project being updated to Swift 2.0 (thanks @dearprakash)!





This blog is licensed under Attribution-Noncommercial-Share Alike 3.0 Unported license.



comments powered by Disqus