Swift Codable:具有字典的数组数组

Posted

技术标签:

【中文标题】Swift Codable:具有字典的数组数组【英文标题】:Swift Codable: Array of Array having Dictionaries 【发布时间】:2019-04-23 10:56:22 【问题描述】:

我有一个 JSON 对象,我不知道如何访问给定 JSON 中的 exclude_list

"variants":
    "variant_groups":
            [
                    
                        "group_id":"1",
                        "name":"Crust",
                        "variations":[
                            "name":"Thin","price":0,"default":1,"id":"1","inStock":1,
                            "name":"Thick","price":0,"default":0,"id":"2","inStock":1,"isVeg":1,
                            "name":"Cheese burst","price":100,"default":0,"id":"3","inStock":1,"isVeg":1],

                    
                        "group_id":"3",
                        "name":"Sauce",
                        "variations":[
                            "name":"Manchurian","price":20,"default":0,"id":"20","inStock":1,"isVeg":0,
                            "name":"Tomato","price":20,"default":0,"id":"21","inStock":1,"isVeg":1,
                            "name":"Mustard","price":20,"default":0,"id":"22","inStock":1,"isVeg":0]

                    ],
            "exclude_list":[
                [
                    "group_id":"1","variation_id":"3",
                    "group_id":"2","variation_id":"10"
                ],
                [
                    "group_id":"2","variation_id":"10",
                    "group_id":"3","variation_id":"22"
                ]
            ]
    

我可以使用下面的Struct 访问以下属性:variantsvariant_groups

public struct VariantResponse: Codable 

    public let variants: Variants

public struct Variants: Codable 

    public let variantGroups:[VariantGroup]
    public let excludeList:[ExcludeItems]

public struct VariantGroup: Codable 
    public let groupId: String
    public let name: String
    public let variations: [Variant]

public struct Variant: Codable 
    public let name: String
    public let price: Int
    public let defaultValue: Int
    public let id: String
    public let inStock: Int
    public var isVeg: Int?

    private enum CodingKeys : String, CodingKey 
        case name, price, defaultValue = "default", id, inStock, isVeg
        

public struct ExcludeItems: Codable 
    public let excludes:[Exclude]

public struct Exclude: Codable 
    public let groupId: String
    public let variationId: String

【问题讨论】:

【参考方案1】:

你可以试试

struct VariantResponse: Codable 
    let variants: Variants


struct Variants: Codable 
    let variantGroups: [VariantGroup]
    let excludeList: [[ExcludeItems]]



struct ExcludeItems: Codable 
    let groupId, variationId: String



do 

    let dec = JSONDecoder()
    dec.keyDecodingStrategy = .convertFromSnakeCase
    let res = try dec.decode(VariantResponse.self, from: data)


catch 

    print(error)

ExcludeItems 包含 groupId, variationId 但您添加了未知密钥 excludes

【讨论】:

【参考方案2】:

您在可解码结构中遇到了一些问题,请尝试使用此代码:

    public struct VariantResponse: Codable 
    public let variants: Variants


public struct Variants: Codable 
    public let variant_groups:[VariantGroup]
    public let exclude_list:[[Exclude]]


public struct VariantGroup: Codable 
    public let group_id: String
    public let name: String
    public let variations: [Variant]


public struct Variant: Codable 
    public let name: String
    public let price: Int
    public let defaultValue: Int
    public let id: String
    public let inStock: Int
    public var isVeg: Int?

    private enum CodingKeys : String, CodingKey 
        case name, price, defaultValue = "default", id, inStock, isVeg
    


public struct Exclude: Codable 
    public let group_id: String
    public let variation_id: String

祝你好运。

【讨论】:

【参考方案3】:

问题可能与模型中的编码键有关。请参考以下模型来获取您的 JSON 结构。

struct VariantsResponse: Codable 
    let variants: Variants?


typealias VariantGroups = [VariantGroup]
typealias ExcludeLists = [[ExcludeList]]
typealias Variations = [Variation]

struct Variants: Codable 
    let variantGroups: VariantGroups?
    let excludeList: ExcludeLists?

    enum CodingKeys: String, CodingKey 
        case variantGroups = "variant_groups"
        case excludeList = "exclude_list"
    


struct ExcludeList: Codable 
    let groupId, variationId: String?

    enum CodingKeys: String, CodingKey 
        case groupId = "group_id"
        case variationId = "variation_id"
    


struct VariantGroup: Codable 
    let groupId, name: String?
    let variations: Variations?

    enum CodingKeys: String, CodingKey 
        case groupId = "group_id"
        case name, variations
    


struct Variation: Codable 
    let name: String?
    let price, variationDefault: Int?
    let id: String?
    let inStock, isVeg: Int?

    enum CodingKeys: String, CodingKey 
        case name, price
        case variationDefault = "default"
        case id, inStock, isVeg
    

在上面的模型中,我正在为以下数组创建类型别名,以使模型更易于阅读和理解。

typealias VariantGroups = [VariantGroup]
typealias ExcludeLists = [[ExcludeList]]
typealias Variations = [Variation]

这里我们为不能直接转换为模型属性的变量定义codingKeys case。

希望这将有助于您创建模型。

您可以使用以下代码使用 responseData 简单地解码模型

let decoder = JSONDecoder()
let res = try decoder.decode(VariantsResponse.self, from: responseData)

这里如果我们指定decoder.keyDecodingStrategy = .convertFromSnakeCase,我们就不需要像case groupId = "group_id"那样指定codingKeys。系统会自动检查_字符,并将JSON密钥字符串转换为camelCaseKeys。

【讨论】:

以上是关于Swift Codable:具有字典的数组数组的主要内容,如果未能解决你的问题,请参考以下文章

使用字典/数组初始化符合 Codable 的对象

快速解码 JSON 数组或字典错误

如何在 swift 4 Codable 中手动解码数组?

Swift IOS 无法使用 Codable 访问 json 数组数据

Swift Codable,数组值作为键

使用 swift Codable 从 JSON 数组中提取数据