带有动态键的Swift Codable

Mas*_*sta 4 json swift swift4 codable

我有JSON结构为:

"periods": {
    "2018-06-07": [
      {
        "firstName": "Test1",
        "lastName": "Test1"
      }
    ],
    "2018-06-06": [
      {
        "firstName": "Test1",
        "lastName": "Test1"
      }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我试图这样解析:

public struct Schedule: Codable {
    public let periods: Periods
}

public struct Periods: Codable {
    public let unknown: [Inner]

    public struct Inner: Codable {
        public let firstName: String
        public let lastName: String
    }

    private struct CustomCodingKeys: CodingKey {
        var stringValue: String
        init?(stringValue: String) {
            self.stringValue = stringValue
        }

        var intValue: Int?
        init?(intValue: Int) {
            return nil
        }
    }

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CustomCodingKeys.self)
        self.unknown = try container.decode([Inner].self, forKey: CustomCodingKeys(stringValue: "2018-06-06")
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我只能得到一个值的结果(2018-06-06)。我在这里要解析多个日期。这可能吗?

Mas*_*sta 17

好的,所以我是这样想出来的:

public struct Schedule: Codable {
    public let periods: Periods
}

public struct Periods: Codable {
    public var innerArray: [String: [Inner]]
    
    public struct Inner: Codable {
        public let firstName: String
        public let lastName: String
    }
    
    private struct CustomCodingKeys: CodingKey {
        var stringValue: String
        init?(stringValue: String) {
            self.stringValue = stringValue
        }
        var intValue: Int?
        init?(intValue: Int) {
            return nil
        }
    }
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CustomCodingKeys.self)
        
        self.innerArray = [String: [Inner]]()
        for key in container.allKeys {
            let value = try container.decode([Inner].self, forKey: CustomCodingKeys(stringValue: key.stringValue)!)
            self.innerArray[key.stringValue] = value
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果我得到了这样的字典:["2018-06-06": [Inner]]键是这个日期字符串,值是内部。

  • 亲爱的 Masta 什么是 CustomCodingKeys? (2认同)

Dav*_*rry 6

假设您省略了,{并且}将围绕该块,并且要使该块成为有效JSON,以下是获取解析的最简单的解决方案,CodingKey由于您的名称与中的键匹配,因此您实际上根本不需要处理JSON,因此综合功能CodingKey可以正常工作:

public struct Schedule: Codable {
    public let periods : [String:[Inner]]
}

public struct Inner: Codable {
    public let firstName: String
    public let lastName: String
}

let schedule = try? JSONDecoder().decode(Schedule.self, from: json)

print(schedule?.periods.keys)

print(schedule?.periods["2018-06-07"]?[0].lastName)
Run Code Online (Sandbox Code Playgroud)

关键是外部JSON是具有单个键periods 的JSON对象(字典/映射)。该键的值是另一个数组映射。像这样分解它,一切都会自动消失。