json Swift Codable支持动态键

x4shl7ld  于 2023-06-07  发布在  Swift
关注(0)|答案(3)|浏览(126)

我有一个 *JSON结构 *:

"periods": {
    "2018-06-07": [
      {
        "firstName": "Test1",
        "lastName": "Test1"
      }
    ],
    "2018-06-06": [
      {
        "firstName": "Test1",
        "lastName": "Test1"
      }
    ]
}

我试着这样解析它:

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")
    }
}

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

yv5phkfx

yv5phkfx1#

假设你省略了{},它们将围绕这个块,并且需要这个块才能成为有效的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)

关键是外部JSON是一个JSON对象(字典/Map),只有一个键periods,该键的值是另一个数组Map。就像这样把它分解,所有的东西都会自动福尔斯出来。

q9yhzks0

q9yhzks02#

好吧,我是这样想的:

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
        }
    }
}

我的字典是这样的:["2018-06-06": [Inner]],其中key是此日期字符串,值为Inner。

js5cn81o

js5cn81o3#

我认为JSON应该在开头加上{,在结尾加上},这样才是有效的JSON,然后你可以很容易地用这样的代码提取句点:

struct Period: Decodable {
    let firstName: String, lastName: String
}

let schedule = try? JSONDecoder().decode([String:[String:[Period]]].self, from: jsonData!)
let periods = schedule?.values.first?.values

相关问题