I don't want to include the library as much as possible! Have you ever thought so?
As a starting point, replacing SwiftyJson used for JSON decoding with pure Swift had only merit, so I will write it down here. Let's decode json with a standard Swift function called JSONDecoder.
It's a great thing that makes struct / class decodable just by inheriting it.
import Foundation
struct User: Decodable {
  var name: String
  var age: Int
}
let json = """
{
  "name": "Bob",
  "age": 20,
}
"""
let jsonData = json.data(using: .utf8)!
let user = try JSONDecoder().decode(User.self, from: jsonData)
that's all. In struct, json is stored in struct. It's simple and easy to use.
print(user.name) // Bob
print(user.age) // 20
Of course, you can also decode JSON whose root is an array. Also, if there is a key applied to json, it is expressed as an optional type.
import Foundation
let json = """
[
    {
        "name": "Bob",
        "age": 30,
        "password": "foo"
    },
    {
        "name": "Ben",
        "age": 20
    }
]
""".data(using: .utf8)!
struct User: Decodable {
    var name: String
    var age: Int
    var password: String?
}
let users = try JSONDecoder().decode([User].self, from: json)
for user in users {
    print(user)
}
//result
// User(name: "Bob", age: 30, password: Optional("foo"))
// User(name: "Ben", age: 20, password: nil)
The name of the json key and the name of the swift object key may be different. For example, when the json key is user_id and the swift object key is userId. Since decoding cannot be performed as it is, use Decodable's CodingKeys enum to enable decoding.
import Foundation
let json = """
[
    {
        "name": "Bob",
        "age": 30,
        "password": "foo",
        "user_id": 1
    },
    {
        "name": "Ben",
        "age": 20,
        "user_id": 2
    }
]
""".data(using: .utf8)!
struct User: Decodable {
    var name: String
    var age: Int
    var password: String?
    var userId: Int
    
    private enum CodingKeys: String, CodingKey {
        case name
        case age
        case password
        case userId = "user_id"
    }
}
let users = try JSONDecoder().decode([User].self, from: json)
for user in users {
    print(user)
}
You have successfully mapped the user_id to the userId.
Decodable can be nested.
struct User: Decodable {
    let name: String
    let children: [Child]
    
    struct Child: Decodable {
        let name: String
        let teachers: [Teacher]
        
        struct Teacher: Decodable {
            let name: String
        }
    }
}
Therefore, it is possible to easily represent a nested JSON data structure.
import Foundation
let json = """
[
    {
        "name": "A",
        "children": [
            {
                "name": "B",
                "teachers": [
                    {
                        "name": "C"
                    }
                ]
            }
        ]
    },
    {
        "name": "E",
        "children": [
            {
                "name": "F",
                "teachers": [
                    {
                        "name": "G"
                    },
                    {
                        "name": "I"
                    }
                ]
            }
        ]
    }
]
""".data(using: .utf8)!
let users = try JSONDecoder().decode([User].self, from: json)
// [
//   User(
//     name: "A",
//     children: [
//       Child(
//         name: "B",
//         teachers: [ Teacher(name: "C") ]
//       )
//     ]
//   ),
//   User(
//     name: "E",
//     children: [
//       Child(
//         name: "F",
//         teachers: [ Teacher(name: "G"), Teacher(name: "I") ]
//       )
//     ]
//   )
// ]
        Recommended Posts