【问题标题】:Swift Json Decodable data structure, varying values in single arraySwift Json可解码数据结构,单个数组中的不同值
【发布时间】:2020-04-07 15:04:33
【问题描述】:

我在做什么

"meta_data": [
        {
            "id": 4116,
            "key": "_wcf_frm_created",
            "value": ""
        },
        {
            "id": 4117,
            "key": "_wcf_custom_degin_checkbox",
            "value": ""
        },
        {
            "id": 4118,
            "key": "_wcf_frm_data",
            "value": {
                "1": {
                    "1": "",
                    "2": "",
                    "3": "chk_box"
                }
            }
        },
        {
            "id": 4142,
            "key": "_vendor_select",
            "value": "6484"
        },
        {
            "id": 4143,
            "key": "_vendor_percentage",
            "value": "100"
        },
        {
            "id": 4144,
            "key": "_vendor_pro_cat",
            "value": "Sushi"
        },
        {
            "id": 4156,
            "key": "slide_template",
            "value": "default"
        }
    ],
    "_links": {
        "self": [
            {
                "href": "https://xxxxxx.net/wp-json/wc/v3/products/6489"
            }
        ],
        "collection": [
            {
                "href": "https://xxxxxx.net/wp-json/wc/v3/products"
            }
        ]
    }

我目前拥有的

struct woocomerceProduct : Decodable, Encodable
{
    var meta_data : [Meta_data?]
    var _links : [_Links?]


}

    struct Meta_data : Decodable, Encodable
{
    var id : Int?
    var key : String?
    var value : String?
}
   struct One : Decodable, Encodable
{
        var one : String?
        var two : String?
        var three : String?
}

struct _Links : Decodable, Encodable
{
    var SELF : [String?]
    var collectio : [String?]
}

好的,这里有问题。 1. id 4118. value 从 String 到 obj,我如何编码这部分? 2.它还使用了一个变量字符串“1”,“2”……我不能用整数作为变量,所以我拼出来了?应该可以。 3.这里的值是self,我不能使用变量self,因为它会认为它是一个self属性。所以我只是把它大写了。

我看了这个,我相信这与我需要做的事情相似,但由于这是一个对象和一个字符串之间,我不确定我需要在这里编写什么代码。 Swift structures: handling multiple types for a single property

【问题讨论】:

  • var _links : _Links?必须是一个对象而不是一个数组。
  • ==> 对于 SELF,您需要使用编码键。枚举 CodingKeys: String, CodingKey { case SELF = "self" }

标签: json swift codable swift5 decodable


【解决方案1】:

试试这个链接将你的 json 转换成 Codable 模型link

    import Foundation

// MARK: - Welcome
struct Welcome: Codable {
    let metaData: [MetaDatum]
    let links: Links

    enum CodingKeys: String, CodingKey {
        case metaData = "meta_data"
        case links = "_links"
    }
}

// MARK: - Links
struct Links: Codable {
    let linksSelf, collection: [Collection]

    enum CodingKeys: String, CodingKey {
        case linksSelf = "self"
        case collection
    }
}

// MARK: - Collection
struct Collection: Codable {
    let href: String
}

// MARK: - MetaDatum
struct MetaDatum: Codable {
    let id: Int
    let key: String
    let value: ValueUnion
}

enum ValueUnion: Codable {
    case string(String)
    case valueClass(ValueClass)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        if let x = try? container.decode(ValueClass.self) {
            self = .valueClass(x)
            return
        }
        throw DecodingError.typeMismatch(ValueUnion.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ValueUnion"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .string(let x):
            try container.encode(x)
        case .valueClass(let x):
            try container.encode(x)
        }
    }
}

// MARK: - ValueClass
struct ValueClass: Codable {
    let the1: [String: String]

    enum CodingKeys: String, CodingKey {
        case the1 = "1"
    }
}

【讨论】:

  • 非常有趣的链接,我会尝试使用它,但是当我们可以使用可解码时,它使用可编码,有可解码的版本吗?我想没关系
  • Swift 4 版本以后支持 Codable 协议,所以不会有问题。
  • Vasu,如果您想对某人发表评论,请在其用户名前添加@,例如,使用“@PranavKasetti”对Pranav 发表评论。
  • @HovercraftFullOfEels 好
  • 这行得通,感谢您的链接!如果我早点知道这一点,会为我节省很多时间
【解决方案2】:

不必要的选项太多,不必要的下划线字符太多。

  1. 要解码两种不同类型的 enum 和关联类型是合理的。
  2. 代码解码字典[String:[String:String]]
  3. 要映射不适当的键,请提供 CodingKeys。

struct WoocomerceProduct : Decodable {
    let metaData : [Meta]
    let links : Links

    private enum CodingKeys : String, CodingKey { case metaData  = "meta_data", links = "_links" }
}

struct Meta : Decodable {
    let id : Int
    let key : String
    let value : StringOrDictionary
}

struct Links : Decodable {
    let myself : [URLType]
    let collection : [URLType]

    private enum CodingKeys : String, CodingKey { case myself  = "self", collection }
}

struct URLType : Decodable {
    let href : URL
}


enum StringOrDictionary : Decodable {
    case string(String), dictionary([String:[String:String]])

    init(from decoder : Decoder) throws
    {
        let container = try decoder.singleValueContainer()
        do {
            let stringData = try container.decode(String.self)
            self = .string(stringData)
        } catch DecodingError.typeMismatch {
            let dictionaryData = try container.decode([String:[String:String]].self)
            self = .dictionary(dictionaryData)
        }
    }
}

【讨论】:

  • 我看到这里,你用let而不是var,元数据中的一些值可以是空的,即使你写了let这也行吗?
  • let 只是一个声明为常量(不可变)。如果缺少键,则将相应的结构成员声明为可选。顺便说一句,如果结构永远不会被编码,请删除Encodableconfomance。
  • imgur.com/a/DEybvQ3 如果我删除枚举,它会删除错误,我可以将枚举移动到其他地方吗?此外,您会看到其他人,因为这并不是所有 api 都推出的。但是你的代码是在底部实现的
  • 我的答案适用于问题中给定的 JSON。如果真实数据完全不同,那是没有意义的。我稍后会删除我的答案。
  • 因此我的回复是imgur.com/a/Pwbpzdz,因此我没有将其添加到整个问题中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
  • 2018-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多