swift json反序列化是错误的

时间:2018-05-18 22:45:01

标签: json swift

使用postman我验证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
    }

我在网站json4swift.com上使用了这个json(完整列表,上面已经缩短了)来构建我的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.AccountRoom重复,请参见下方的截图 enter image description here

为什么要像我那样反序列化我的对象?

1 个答案:

答案 0 :(得分:1)

我已经检查了你的代码,稍作修改,否则代码不起作用:我使用相同的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)
}

运作良好并打印:

  

对象:房间(id:可选(“506e9a1d-cded-4853-a9df-7f8a57d6550d”),   name:可选(“TeleTwo”),shortName:可选(“2”),displayName:   可选(“2”),inService:可选(true),托管:可选(true),   capacity:可选(2),schedulingOption:可选(“VC Scheduling”),   location:可选(sss.Location(id:   可选(“50b07258-2668-416e-aef4-a8a48e9e7389”),姓名:   可选(“远程呈现测试”),shortName:可选(“远程呈现”   测试“),displayName:可选(”远程呈现测试“),城市:   可选(“Nash”),国家/地区:可选(“美国”),帐户:   可选(sss.Account(ID:   可选(“509788c6-197f-40f1-a7f7-274a23af9062”),名称:   Swift.ImplicitlyUnwrappedOptional.some( “发展”),   简称:   Swift.ImplicitlyUnwrappedOptional.some( “开发”),   显示名称:   Swift.ImplicitlyUnwrappedOptional.some(“Dev”),活跃:   Swift.ImplicitlyUnwrappedOptional.some(真),   exchangeEnabled:   Swift.ImplicitlyUnwrappedOptional.some(false),tmsEnabled:   Swift.ImplicitlyUnwrappedOptional.some(假),   commProxyEnabled:   Swift.ImplicitlyUnwrappedOptional.some(true),服务:   Swift.ImplicitlyUnwrappedOptional&GT;。一些([ “超级”,   “VMR_Pool_Static”,“VMR”]))),纬度:可选(45.786368000000003),   经度:可选(-78.505821999999995),有效:可选(false),   摘要:nil)),summary:可选([“totalDevices”:2]),vip:   可选(假))

似乎一切正常。