This is how I parse JSON in Swift

Third party libraries are great. I am even guilty of releasing a couple of them myself, but the thing is that I believe pulling in a third party dependency should be carefully considered.

The advantages and disadvantages, the benefits and risks of relying on third party libraries are definitelly worth a separate post. But, for now, let me just say that I think relying on third party code is a commitment that needs to be very carefully considered. It is a dependency on code that is out of your control.

But back to the post at hand. Even though the existing third party JSON parsers and serializers are great, I tend to do all my JSON parsing manually.

Why? First of all, check the previous paragraph. I am not for reinventing the wheel at all, but so far, I haven’t found myself in any situation where relying on a third party library had any sensible advantages over rolling out my own parsing.

An object should know how to serialize and materialize itself. Now, when it comes to simple model objects (kind of a POJO), it could be argued that embedding that knowledge into an object is not the best possible idea. After all, the NSCoding approach implies that a model object would need to know the specifics of a format (JSON, XML, plist, or whatever the cool kids do at the moment), and that knowledge should not be part of the model object itself.

But Swift provides awesome tools to model this in a modular way. Like, for example, extensions. So we could still declare our model object as a simple entity, without any behaviour:

1

2

3

4

5

6

7

structBlogPost{

let id:Int

let text:String

let thumbURL:NSURL

let linkURL:NSURL

}

And then declare a failable initializer that creates an instance of BlogPost from JSON data in an extension:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

extensionBlogPost{

privatestructKeys{

staticlet id="id"

staticlet text="text"

staticlet thumbURL="thumb_url"

staticlet linkURL="link_url"

}

init?(JSON:AnyObject){

guard let id=JSON[Keys.id]as?Int,

let text=JSON[Keys.text]as?String,

let jsonThumbURL=JSON[Keys.thumbURL]as?String,

let jsonLinkURL=JSON[Keys.linkURL]as?String,

let thumbURL=NSURL(string:jsonThumbURL),

let linkURL=NSURL(string:jsonLinkURL)else{

returnnil

}

self.id=id

self.text=text

self.thumbURL=thumbURL

self.linkURL=linkURL

}

}

The code looks clean enough to me, I am still complying to the single responsibility principle, and I still have good separation of concerns.

If I needed to materialize a BlogPost from a different format, say a plist file, all I would need to do would be add a new extension with a new failable initializer.