【问题标题】:Type 'AreaData' does not conform to protocol 'Encodable'类型“AreaData”不符合协议“Encodable”
【发布时间】:2019-07-24 06:49:44
【问题描述】:

当我为我的 JSON 文件制作模型时,我得到了这两个错误。

1) 我在 AreaData 结构中遇到了一致性错误

2) “AnyObject 不能用作符合协议Decodable 的类型,因为Decodable 具有静态要求”初始化程序中的错误。

我尝试了多种方法,但找不到正确的解决方案。如何为这个嵌套/复杂的 JSON 制作合适的模型?

这是我的 JSON 文件。这个数据是嵌套的

[
    {
        "ID": "01",
        "Name": "Area 01",
        "parentId": null,
        "sublevel": [
            {
                "ID": "01-01",
                "Name": "Building 01",
                "On": "",
                "Off": "",
                "parentId": "01",
                "sublevel": [
                    {
                        "ID": "01-01-01",
                        "Name": "Flat 01",
                        "On": "",
                        "Off": "",
                        "parentId": "01-01",
                        "sublevel": []
                    }
                ]
            },
            {
                "ID": "01-02",
                "Name": "Building 02",
                "On": "01",
                "Off": "03",
                "parentId": "01",
                "sublevel": [
                    {
                        "ID": "01-02-01",
                        "Name": "Flat 01",
                        "On": "",
                        "Off": "",
                        "parentId": "01-02",
                        "sublevel": []
                    },
                    {
                        "ID": "01-02-02",
                        "Name": "Flat 02",
                        "On": "01",
                        "Off": "02",
                        "parentId": "01-02",
                        "sublevel": []
                    },
                    {
                        "ID": "01-02-03",
                        "Name": "Flat 03",
                        "On": "02",
                        "Off": "12",
                        "parentId": "01-02",
                        "sublevel": [
                            {
                                "ID": "01-02-03-01",
                                "Name": "Room 01",
                                "On": "",
                                "Off": "",
                                "parentId": "01-02-03",
                                "sublevel": []
                            },
                            {
                                "ID": "01-02-03-02",
                                "Name": "Room 02",
                                "On": "",
                                "Off": "",
                                "parentId": "01-02-03",
                                "sublevel": []
                            },
                            {
                                "ID": "01-02-03-03",
                                "Name": "Room 03",
                                "On": "02",
                                "Off": "03",
                                "parentId": "01-02-03",
                                "sublevel": []
                            },
                            {
                                "ID": "01-02-03-04",
                                "Name": "Room 04",
                                "On": "",
                                "Off": "",
                                "parentId": "01-02-03",
                                "sublevel": []
                            },
                            {
                                "ID": "01-02-03-05",
                                "Name": "Room 05",
                                "On": "01",
                                "Off": "",
                                "parentId": "01-02-03",
                                "sublevel": []
                            }
                        ]
                    },
                    {
                        "ID": "01-02-04",
                        "Name": "Flat 04",
                        "On": "12",
                        "Off": "03",
                        "parentId": "01-02",
                        "sublevel": []
                    },
                    {
                        "ID": "01-02-05",
                        "Name": "Flat 05",
                        "On": "02",
                        "Off": "",
                        "parentId": "01-02",
                        "sublevel": []
                    }
                ]
            },
            {
                "ID": "01-03",
                "Name": "Building 03",
                "On": "02",
                "Off": "01",
                "parentId": "01",
                "sublevel": []
            },
            {
                "ID": "01-04",
                "Name": "Building 04",
                "On": "",
                "Off": "",
                "parentId": "01",
                "sublevel": []
            }
        ]
    }
]

这是我的模型类

import Foundation
struct AreaData : Codable {

    let iD : String?
    let name : String?
    let parentId : AnyObject?
    let sublevel : [Sublevel]?

    enum CodingKeys: String, CodingKey {
        case iD = "ID"
        case name = "Name"
        case parentId = "parentId"
        case sublevel = "sublevel"
    }

    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)
        parentId = try values.decodeIfPresent(AnyObject.self, forKey: .parentId)
        sublevel = try values.decodeIfPresent([Sublevel].self, forKey: .sublevel)
    }

}

struct Sublevel : Codable {

    let on : String?
    let iD : String?
    let name : String?
    let off : String?
    let parentId : String?
    let sublevel : [Sublevel]?

    enum CodingKeys: String, CodingKey {
        case on = "On"
        case iD = "ID"
        case name = "Name"
        case off = "Off"
        case parentId = "parentId"
        case sublevel = "sublevel"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        on = try values.decodeIfPresent(String.self, forKey: .on)
        iD = try values.decodeIfPresent(String.self, forKey: .iD)
        name = try values.decodeIfPresent(String.self, forKey: .name)
        off = try values.decodeIfPresent(String.self, forKey: .off)
        parentId = try values.decodeIfPresent(String.self, forKey: .parentId)
        sublevel = try values.decodeIfPresent([Sublevel].self, forKey: .sublevel)
    }

}

【问题讨论】:

  • 问题出在 AnyObject 上。 Codabe 不支持 Any 或 AnyObject 之类的东西。您需要明确指定类型。
  • 在SubLevel parentId 是一个字符串,有什么理由相信它在顶层(AreaData)不一样?

标签: json swift codable


【解决方案1】:

试试这个,

 struct AreaDataModel: Codable {
    let id, name: String
    let parentID: String? // AnyObject can't conform to Encodable protocol .  
    let sublevel: [Sublevel]

    enum CodingKeys: String, CodingKey {
        case id = "ID"
        case name = "Name"
        case parentID = "parentId"
        case sublevel
    }
}

// MARK: - Sublevel
struct Sublevel: Codable {
    let id, name, on, off: String
    let parentID: String
    let sublevel: [Sublevel]

    enum CodingKeys: String, CodingKey {
        case id = "ID"
        case name = "Name"
        case on = "On"
        case off = "Off"
        case parentID = "parentId"
        case sublevel
    }
}

typealias AreaData = [AreaDataModel]

我推荐this 工具简单快速。

【讨论】:

    【解决方案2】:

    问题出在AnyObjectCodabe 不支持 AnyAnyObject 之类的东西。您需要明确指定类型。

    在您添加的 JSON 响应 中,parentIdnullString。因此,您可以使用String? 作为其类型,即

    struct AreaData : Codable {
        let parentId : String? //here.....
        //rest of the code....
    }
    

    此外,如果 propertykey 完全匹配,则无需在 enum CodingKeys 中显式指定 caserawValue。所以struct AreaData中的CodingKeys一定是,

    enum CodingKeys: String, CodingKey {
        case iD = "ID"
        case name = "Name"
        case parentId, sublevel
    }
    

    此外,init(from decoder: Decoder) 不是必需的。这是因为您没有在其中进行任何特定的解析。直接解析将由Codable 自己处理。

    所以,struct AreaData 应该看起来像,

    struct AreaData : Codable {
        let iD : String?
        let name : String?
        let parentId : String?
        let sublevel : [Sublevel]?
    
        enum CodingKeys: String, CodingKey {
            case iD = "ID"
            case name = "Name"
            case parentId, sublevel
        }
    }
    

    也对struct Sublevel 进行类似的更改。

    此外,仅当您希望同时编码和解码数据时才使用Codable。如果您需要单一功能,即编码或解码,请改用EncodableDecodable

    推荐:

    由于AreaDataSublevel 包含几乎相同类型的数据,您可以使用单个structdecodeJSON,即

    struct AreaData: Decodable {
        let iD : String?
        let name : String?
        let parentId : String?
        let sublevel : [AreaData]?
        let on : String?
        let off : String?
    
        enum CodingKeys: String, CodingKey {
            case iD = "ID"
            case name = "Name"
            case on = "On"
            case off = "Off"
            case parentId, sublevel
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      相关资源
      最近更新 更多