3

I'm using Swift 4 Codable and I'm receiving this JSON from my web service:

{
    "status": "success",
    "data": {
        "time": "00:02:00",
        "employees": [
            {
                "id": 001,
                "name": "foo"
            }, 
            {
                "id": 002,
                "name": "bar"
            }
        ]
    }
}

I want to decode only employees array into employee objects (the time property will only be saved once), but nothing works.
I read a lot of materials about Swift 4 Codable but don't get how can I decode this array.

EDIT: My employee class:

import Foundation

struct Employee: Codable {
    var id: Int
    var time: Date

    enum CodingKeys: String, CodingKey {
        case id = "id"
        case time = "time"
    }
}

The request:

  Alamofire.SessionManager.default.request(Router.syncUsers)
            .validate(contentType: ["application/json"])
            .responseJSON { response in
                if response.response?.statusCode == 200 {
        guard let jsonDict = response as? Dictionary<String, Any>,
                    let feedPage = Employee(from: jsonDict as! Decoder) else {
                    return
                }

                guard let response = response.result.value as? [String: Any] else {
                    return
                }

                guard let data = response["data"] as? [String: Any] else {
                    return
                }

                guard let users = data["employees"] else {
                    return
                }

                guard let usersData = try? JSONSerialization.data(withJSONObject: users, options: .prettyPrinted) else {
                    return
                }

                guard let decoded = try? JSONSerialization.jsonObject(with: usersData, options: []) else {
                    return
                }

                let decoder = JSONDecoder()

                guard let employee = try? decoder.decode(Employee.self, from: usersData) else {
                    print("errorMessage")
                    return
                }
                } else {
                    print("errorMessage")
                }
        }
3
  • Did you actually look at your code and the JSON response in your question? You're clearly looking for a key named users in your response, when your example response shows a key named employees. Moreover, your approach is clearly wrong. You already parse the response as JSON using Alamofire, then you reencode part of it to JSON just to be able to use JSONDecoder to decode it from Data. That makes no sense. Either do the whole JSON parsing in a type-safe manner using Codable and JSONDecoder or do it dynamically using Alamofire's responseJSON. Commented Mar 18, 2018 at 18:33
  • sorry, the key is employees... i changed the json recently. but still doesnt work :/ could you post an example of an decode for that code. I know that this code doesnt make much sense, but I'm changing the code for the last hour and dont get success . this is a simple task I know, but I cant make it work yet :( Commented Mar 18, 2018 at 18:37
  • Numbers can't start with 0 in JSON (except for numbers in the range 0 <= x < 1), so 001 is not JSON. Commented Mar 19, 2018 at 20:13

2 Answers 2

6

When using Codable you cannot decode inner data without decoding the outer.

But it's pretty simple, for example you can omit all CodingKeys.

struct Root : Decodable {
    let status : String
    let data : EmployeeData
}

struct EmployeeData : Decodable {
    let time : String
    let employees : [Employee]
}

struct Employee: Decodable {
    let id: Int
    let name: String
}

let jsonString = """
{
    "status": "success",
    "data": {
        "time": "00:02:00",
        "employees": [
            {"id": 1, "name": "foo"},
            {"id": 2, "name": "bar"}
        ]
    }
}
"""


do {
    let data = Data(jsonString.utf8)
    let result = try JSONDecoder().decode(Root.self, from: data)
    for employee in result.data.employees {
        print(employee.name, employee.id)
    }
} catch { print(error) }
Sign up to request clarification or add additional context in comments.

2 Comments

What's the difference between Codable and Decodable/Encodable?
The definition of Codable is Decodable & Encodable that means it conforms to both.
2

You can solve this kind of JSON parsing problem very easily with quicktype. Just paste in your JSON on the left and you'll get types and serialization/deserialization code on the right, for a variety of languages. Here are the types it produces for your JSON:

struct Employees: Codable {
    let status: String
    let data: EmployeesData
}

struct EmployeesData: Codable {
    let time: String
    let employees: [Employee]
}

struct Employee: Codable {
    let id: Int
    let name: String
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.