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

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.]

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 simple model

Including an initializer init(_:) that takes in a JSONDecoder object and is responsible for the translation between JSON properties and RepoOwner properties

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:

A simple model

Representing the model as a class with variable - i.e. non-constant - properties which must also be Optionals

Having the class conform to the Mappable protocol

Including a required failable initializer init(_:), that takes in a Map object and calls the mapping(_:) function

Including a mapping(_:) function that represents the translation between JSON properties and RepoOwner properties

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:

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