Uncategorized

Convenient iOS JSON Parsing with Eson

As a mobile developer, I routinely work with JSON from APIs. Going from a JSON dictionary to a model object is something I do for just about every screen I build. On Android, I use a wonderful library called Gson which (more or less) automatically take JSON and populates a model object with the data. It’s magical to just say:

SomeModel model = new Gson().fromJson(json, SomeModel.class)

and be done!

For iOS, and specifically Swift, it’s another story. There are a few ways you can accomplish this:

  1. Manually map the JSON keys/values to properties.
  2. Use a library like ObjectMapper or Argo.

In either case you have to do something I find unpleasant: explicitly say which properties to map to which json keys.

For the vast majority of my own personal use cases, that’s pretty redundant. Most of the time, the properties I’m dealing with are llama case versions of the snake case JSON keys from the server. Most of the time, I don’t have to deal with performance issues. Most of the time, my objects are subclasses of NSObject.

For cases like these, enter Eson.

To be clear, the circumstances described are not 100% of cases. But for those times that I don’t need something specialized, I don’t want to sacrifice usability for a bunch of features I’m not going to need. And it’s those times that I reach for Eson.

Eson

What makes Eson special? It handles the majority of cases for you, but lets you make changes if you want to. Most of the Rails or Node APIs I see around use snake case, and the iOS objects I create use llama case, so Eson’s default is to convert snake case json keys to llama case properties. If your server uses llama case (as many Node APIs do), simply pass Eson a boolean saying not to convert. Or, if you have different names on the server altogether, pass in a dictionary to explicitly map only those keys.

Eson uses reflection to populate properties. The advantage of this is it can auto detect your object’s properties so you don’t have to manually name them. This reduces your model’s size in lines of code, especially for models with a bunch of properties. It also means that just about any NSObject can be deserialized, even ones for which you don’t control the source code.

Eson autodetects the type of the property, and will try to create an object of that type out of the dictionary for that key. This means that most of the time when you have NSObjects with other NSObjects as properties, Eson will be able to traverse down that tree and instantiate all of them without any interaction from you.

Eson isn’t perfect, and there are a few gotchas. Obviously, having to subclass an NSObject is one of them. This is because Swift 3.2/4.0 objects do not have robust reflection of their own yet (you can read properties but you can’t write them, basically). Hopefully in the near future this will change.

Because of NSObject and the lack of robust reflection, there are some weird limitations. Any property that isn’t representable in Objective-C won’t be deserialized. Examples would include Int? and Bool?. These properties can still be represented as NSNumber?s, though, or you can make them simple Ints or Bools with default values. You may also need to deserialize NSArrays separately, since they don’t always declare what type is in the array.

As always, examine your use case

Eson regularly saves me a bunch of code, and allows me to build apps that interact with APIs faster than ever. But as with everything, you should make sure it fits your use case. A good place to start is to check out the tests in the example project on Github, so go! Check it out and start saving time today!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s