Parsing JSON with Swift

Source: Internet
Author: User

This article is translated from this article and all the code in this article is on GitHub.

In this article, I will outline a parsing library that uses Swift to process JSON. A JSON example is as follows:

  1. var json: [String:anyobject] = [
  2. " stat": "OK",
  3. "Blogs": [
  4. "blog": [
  5. [
  6. "id":
  7. " name": "Bloxus test",
  8. "Needspassword": true,
  9. "url": "http://remote.bloxus.com/"
  10. ],
  11. [
  12. "id":
  13. " name": "Manila Test",
  14. "Needspassword": false,
  15. "url": "http://flickrtest1.userland.com/"
  16. ]
  17. ]
  18. ]
  19. ]

The most challenging part is how to convert this data into an array of Swift structures as follows:

    1. struct Blog {
    2. Let Id:int
    3. Let name:string
    4. Let Needspassword:bool
    5. Let Url:nsurl
    6. }

We first look at the final analytic function, which contains two algorithms: >>= and <*>. These two operators may look strange, but parsing the entire JSON structure is as simple as that. The other sections of this article will explain these library codes. The following parsing code works: If the JSON is illegal (for example, name does not exist or ID is not integer) The final result will be nil. We don't need reflection (reflection) and KVO, just a few functions and some clever combinations:

  1. Func Parseblog (blog:anyobject)-blog? {
  2. return asdict (blog) >>= {
  3. Mkblog <*> Int ($,"id")
  4. <*> string ($,"name")
  5. <*> bool ($,"Needspassword")
  6. <*> (String ($, "url") >>= tourl)
  7. }
  8. }
  9. Let parsed: [Blog]? = Dictionary (JSON, "blogs") >>= {
  10. Array ($, "blog") >>= {
  11. Join ($0.map (Parseblog))
  12. }
  13. }

What exactly did the above code do? Let's take a closer look at these most important functions. First look at the dictionary function, which takes a String-to-Anyobject dictionary and returns another dictionary with the specified key:

    1. Dictionary (input: [String:anyobject], key:string), [String:anyobject]? {
    2. return Input[key] >>= {$ as? [String:anyobject]}
    3. }

For example, in the previous JSON example, we expected key = "blogs" to contain a dictionary. If the dictionary exists, the above function returns the dictionary, otherwise nil is returned. We can write the same method for Array, String, and Integer (just life, the full code, see Github):

    1. Func Array (input: [String:anyobject], key:string), [Anyobject]?
    2. Func string (input: [String:anyobject], key:string), string?
    3. Func Int (input: [Nsobject:anyobject], key:string), int?

Now, let's look at the full structure of the JSON example. It is a dictionary in itself and contains a second dictionary with key "blogs". The dictionary contains an Array with a key of "blog". We can use the following code to express the above structure:

    1. If Let blogsdict = Dictionary (parsedjson, "blogs") {
    2. if let Blogsarray = Array (blogsdict, "blog") {
    3. //Do something with the blogs array
    4. }
    5. }

I can implement a >>= operation instead, accept a optional parameter, and use a function on it when the parameter is not nil. The operator uses the flatten function, and the flatten function expands the nested optional:

    1. Operator infix >>= {}
    2. @infix func >>= <u,t> (optional:t, F:t-u?) u? {
    3. return Flatten (Optional.map (f))
    4. }
    5. Func flatten (x:a??), A? {
    6. if let y = x { return y}
    7. return Nil
    8. }

Another frequent use is the <*> operator. For example, the following code is used to parse a single blog:

    1. Mkblog <*> Int (dict,"id")
    2. <*> string (dict,"name")
    3. <*> bool (dict,"Needspassword")
    4. <*> (String (dict, "url") >>= tourl)

This function works when all optional parameters are Non-nil, and the code above translates to:

    1. Mkblog (int (dict,"id"), String (Dict,"name"), BOOL (dict,"Needspassword"), (String (dict, "url") >>= tourl))

So let's take a look at the definition of operator <*>. It takes two optional parameters, and the left argument is a function. If none of the two parameters is nil, the Left function argument is used for the right argument:

    1. operator infix <*> { associativity left  precedence 150 } 
    2. func <*><a, b> (f:  (A -> B)?,  x: a?)  -> b? { 
    3.     if let  f1 = f { 
    4.         if let x1 = x { 
    5.              return f1 (x1)  
    6.         } 
    7.     } 
    8.     return nil 
    9. }  

Now you might want to know what Mkblog is doing. It is a curried function used to wrap our initialization function. First, we have a function (Int,string,bool,nsurl) –> the type of the Blog. The curry function then converts its type to a Blog, Nsurl, a String, such as Int:

    1. Let Mkblog = Curry {ID, name, needspassword, url in
    2. Blog (Id:id, Name:name, Needspassword:needspassword, Url:url)
    3. }

We will use Mkblog and <*>, let's take a look at the first line:

    1. Mkblog:int, Nsurl, String, Bool,
    2. Int (dict, "id"): int?
    3. Let Step1 = mkblog <*> int (dict,"id")

As you can see, using <*> to connect them together, a new type will be returned: (Blog, Nsurl, String---)? , and then combine with the string function:

    1. Let Step2 = Step1 <*> string (dict,"name")

We get: (Blog, Nsurl, Bool)? , has been such a combination, and finally will be the type of Blog? The value.

Hopefully you can now see how the entire code works together. By creating some auxiliary functions and operators, we can make it very easy to parse the strongly typed JSON data. If you don't use the optional type, then we will be using a completely different type and contain some error messages, but this will be the topic of another blog.

Parsing JSON with Swift

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.