3

我有一些以以下格式返回的 JSON,

{
"Random Word": [
    [
        "2017-08-10",
        6
    ],
    [
        "2017-08-11",
        6
    ],
    [
        "2017-08-15",
        4
    ]
],
"Another Random Word": [
    [
        "2017-08-10",
        4
    ],
    [
        "2017-08-11",
        4
    ],
    [
        "2017-08-12",
        1
    ],
    [
        "2017-08-14",
        2
    ],
    [
        "2017-08-15",
        4
    ],
    [
        "2017-08-16",
        1
    ]
]
}

问题是'key'每次都会不同,'value'包含一个异构的字符串数组(应该转换为日期)和整数。

有没有办法使用 Swift 的 Decodable 协议把它变成对象?

这是一个可以解码为的结构,

struct MyJSONData: Decodable {

    var myInfo: Dictionary<String, [[Any]]>?
    ...
}

但是,如果有更好的方法来构建结构,我全神贯注!

提前致谢。

4

2 回答 2

1

我相当肯定您的情况类似于我最近发布的一个问题:Flattening JSON when keys are known only at runtime

如果是这样,您可以使用以下解决方案:

struct MyJSONData: Decodable {
    var dates = [Any]()

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()

        // Only use first item
        let stringItem = try container.decode(String.self)
        dates.append(stringItem)
        let numberItem = try container.decode(Int.self)
        dates.append(numberItem)
    }
}

let decoded = try! JSONDecoder().decode([String : [MyJSONData]].self, from: jsonData).values
// Returns an Array of MyJSONData

工作解决方案:http ://swift.sandbox.bluemix.net/#/repl/59949d74677f2b7ec84046c8

于 2017-08-16T19:27:08.200 回答
1

我正在使用一个 API,它使用像你这样的异构数据对 JSON 数组进行编码,但即使是列的顺序也是事先不知道的 :(

一般来说,我强烈建议不要将数据存储在异构数组中。你很快就会忘记什么索引代表什么属性,更不用说不断地来回转换了。相反,当您从数组解码时,创建一个数据模型来存储它。

需要注意的另一件事是,您的日期不是JSONDecoder默认情况下所期望的。它需要 ISO 8601 格式 ( yyyy-MM-ddTHH:mm:ssZ),而您的日期字符串中缺少时间部分。您可以通过提供自定义来告诉您JSONDecoder要做什么DateFormatter

struct WordData: Decodable {
    var date: Date
    var anInt: Int

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        self.date = try container.decode(Date.self)
        self.anInt = try container.decode(Int.self)
    }
}

var dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_us_POSIX")
dateFormatter.timeZone = TimeZone(identifier: "UTC")
dateFormatter.dateFormat = "yyyy-MM-dd"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)

let words = try decoder.decode([String: [WordData]].self, from: jsonData)
于 2017-08-20T11:51:48.697 回答