быстрая десериализация JSON не так - PullRequest
0 голосов
/ 19 мая 2018

Используя почтальона, я проверяю ответ json (список этих Room объектов)

{
        "id": "506e9a1d-cded-4853-a9df-7f8a57d6550d",
        "name": "TeleTwo",
        "shortName": "2",
        "displayName": "2",
        "inService": true,
        "managed": true,
        "capacity": 2,
        "schedulingOption": "VC Scheduling",
        "location": {
            "id": "50b07258-2668-416e-aef4-a8a48e9e7389",
            "name": "Telepresence Test",
            "shortName": "Telepresence Test",
            "displayName": "Telepresence Test",
            "city": "Nash",
            "country": "United States",
            "account": {
                "id": "509788c6-197f-40f1-a7f7-274a23af9062",
                "name": "Development",
                "shortName": "Dev",
                "displayName": "Dev",
                "active": true,
                "exchangeEnabled": false,
                "tmsEnabled": false,
                "commProxyEnabled": true,
                "services": [
                    "Premier",
                    "VMR_Pool_Static",
                    "VMR"
                ],
                "logo": "/provisioning/image/2472"
            },
            "latitude": 45.786368,
            "longitude": -78.505822,
            "active": false,
            "summary": null
        },
        "summary": {
            "totalDevices": 2
        },
        "vip": false
    }

Я использовал этот json (полный список, приведенный выше сокращен) на сайте json4swift.com, чтобы построить мойОбъекты dto и поместили их в мой проект

Еще раз сокращая длину, если требуется, я могу добавить больше (обновил, чтобы включить все, так как это было частью проблемы):

Room.swift

struct Room : Codable {
    let id : String?
    let name : String?
    let shortName : String?
    let displayName : String?
    let inService : Bool?
    let managed : Bool?
    let capacity : Int?
    let schedulingOption : String?
    let location : Location?
    let summary : RoomSummary?
    let vip : Bool?

enum CodingKeys: String, CodingKey {
    case id = "id"
    case name = "name"
    case shortName = "shortName"
    case displayName = "displayName"
    case inService = "inService"
    case managed = "managed"
    case capacity = "capacity"
    case schedulingOption = "schedulingOption"
    case location
    case summary
    case vip = "vip"
}

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    id = try values.decodeIfPresent(String.self, forKey: .id)
    name = try values.decodeIfPresent(String.self, forKey: .name)
    shortName = try values.decodeIfPresent(String.self, forKey: .shortName)
    displayName = try values.decodeIfPresent(String.self, forKey: .displayName)
    inService = try values.decodeIfPresent(Bool.self, forKey: .inService)
    managed = try values.decodeIfPresent(Bool.self, forKey: .managed)
    capacity = try values.decodeIfPresent(Int.self, forKey: .capacity)
    schedulingOption = try values.decodeIfPresent(String.self, forKey: .schedulingOption)
    location = try Location(from: decoder)
    summary = try RoomSummary(from: decoder)
    vip = try values.decodeIfPresent(Bool.self, forKey: .vip)
}

}

Location.swift

struct Location : Codable {
    let id : String?
    let name : String?
    let shortName : String?
    let displayName : String?
    let city : String?
    let country : String?
    let account : Account?
    let latitude : Double?
    let longitude : Double?
    let active : Bool?
    let summary : LocationSummary?

    enum CodingKeys: String, CodingKey {

        case id = "id"
        case name = "name"
        case shortName = "shortName"
        case displayName = "displayName"
        case city = "city"
        case country = "country"
        case account
        case latitude = "latitude"
        case longitude = "longitude"
        case active = "active"
        case summary  
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decodeIfPresent(String.self, forKey: .id)
        name = try values.decodeIfPresent(String.self, forKey: .name)
        shortName = try values.decodeIfPresent(String.self, forKey: .shortName)
        displayName = try values.decodeIfPresent(String.self, forKey: .displayName)
        city = try values.decodeIfPresent(String.self, forKey: .city)
        country = try values.decodeIfPresent(String.self, forKey: .country)
        account = try Account(from: decoder)
        latitude = try values.decodeIfPresent(Double.self, forKey: .latitude)
        longitude = try values.decodeIfPresent(Double.self, forKey: .longitude)
        active = try values.decodeIfPresent(Bool.self, forKey: .active)
        summary = try LocationSummary(from: decoder)
    }

}

Account.swift

struct Account : Codable {
    let id : String?
    let name : String!
    let shortName : String!
    let displayName : String!
    let active : Bool!
    let exchangeEnabled : Bool!
    let tmsEnabled : Bool!
    let commProxyEnabled : Bool!
    let services : [String]!

    enum CodingKeys: String, CodingKey {
        case id = "id"
        case name = "name"
        case shortName = "shortName"
        case displayName = "displayName"
        case active = "active"
        case exchangeEnabled = "exchangeEnabled"
        case tmsEnabled = "tmsEnabled"
        case commProxyEnabled = "commProxyEnabled"
        case services = "services"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decodeIfPresent(String.self, forKey: .id)
        name = try values.decodeIfPresent(String.self, forKey: .name)
        shortName = try values.decodeIfPresent(String.self, forKey: .shortName)
        displayName = try values.decodeIfPresent(String.self, forKey: .displayName)
        active = try values.decodeIfPresent(Bool.self, forKey: .active)
        exchangeEnabled = try values.decodeIfPresent(Bool.self, forKey: .exchangeEnabled)
        tmsEnabled = try values.decodeIfPresent(Bool.self, forKey: .tmsEnabled)
        commProxyEnabled = try values.decodeIfPresent(Bool.self, forKey: .commProxyEnabled)
        services = try values.decodeIfPresent([String].self, forKey: .services)
    }
}

Моя проблема в том, что Room.Location & Room.Location.Accountявляются дубликатами Room, см. скриншот ниже.
enter image description here

почему он десериализует мои объекты таким образом?

1 Ответ

0 голосов
/ 19 мая 2018

Я проверил ваш код с небольшими исправлениями, в противном случае код не работал: я использовал тот же json, но исправил summary типы свойств:

struct Room : Codable {
    let id : String?
    let name : String?
    let shortName : String?
    let displayName : String?
    let inService : Bool?
    let managed : Bool?
    let capacity : Int?
    let schedulingOption : String?
    let location : Location?
    let summary : Dictionary<String, Int>?
    let vip : Bool?
}

struct Location : Codable {
    let id : String?
    let name : String?
    let shortName : String?
    let displayName : String?
    let city : String?
    let country : String?
    let account : Account?
    let latitude : Double?
    let longitude : Double?
    let active : Bool?
    let summary : String?
}

struct Account : Codable {
    let id : String?
    let name : String!
    let shortName : String!
    let displayName : String!
    let active : Bool!
    let exchangeEnabled : Bool!
    let tmsEnabled : Bool!
    let commProxyEnabled : Bool!
    let services : [String]!
}

do {
    let jsonDecoder = JSONDecoder()
    let object = try jsonDecoder.decode(Room.self, from: data) // Here is Room.self, not [Room].self, due to json root object is dictionary
    print("object: ", object)
} catch {
    print("error: ", error)
}

In работает хорошо и печатает:

объект: Комната (id: Необязательно ("506e9a1d-cded-4853-a9df-7f8a57d6550d"), имя: Необязательно ("TeleTwo"), shortName: Необязательно ("2"), displayName:Необязательно ("2"), inService: Необязательно (true), управляемый: Необязательно (true), емкость: Необязательно (2), schedulingOption: Необязательно ("VC Scheduling"), расположение: Необязательно (sss.Location (id: Необязательно ("50b07258-2668-416e-aef4-a8a48e9e7389"), имя: необязательное («Тест телеприсутствия»), shortName: необязательно («тест телеприсутствия»), displayName: необязательно («тест телеприсутствия»), город: необязательно («Нэш»)), страна: Необязательно ("Соединенные Штаты"), учетная запись: Необязательно (sss.Account (id: Необязательно ("509788c6-197f-40f1-a7f7-274a23af9062"), имя: Swift.ImplicitlyUnwrappedOptional.some ("Разработка"),shortName: Swift.ImplicitlyUnwrappedOptional.some ("Dev"), displayName: Swift.ImplicitlyUnwrappedOptional.some ("Dev"), active: Swift.ImplicitlyUnwrappedOptional.some (true), exchangeEnabled: Swift.ImplicitlyUnwrappedOptional.some (false), tmsEnabled: Swift.ImplicitlyUnwrappedOptional.some (false), commProxyEnableppedOU, services: Swift.ImplicitlyUnwrappedOptional> .some (["Premier", "VMR_Pool_Static", "VMR"]))), широта: необязательная (45.786368000000003), долгота: необязательная (-78.50582199999999995), активная: необязательная (false), сводная: nil)), резюме: Необязательно (["totalDevices": 2]), vip: Необязательно (false))

Кажется, все в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...