雨燕可解码JSON字典异构阵列

问题描述:

我有一些的JSON回来按以下格式,雨燕可解码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 
    ] 
] 
} 

的问题是,“钥匙”将是不同的,每次和“值”中包含的异质字符串数组(应该转换为日期)和Ints。

有没有办法使用Swift的可解码协议来将它变成对象?

这里是它可能被解码为一个结构,

struct MyJSONData: Decodable { 

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

但是,如果有更好的方法来构造结构而言,我所有的耳朵!

在此先感谢。

+0

不能使用任何/ AnyObject。你的数据结构是否稳定?我的意思是,它会始终是一个字符串和一个Int顺序? – nathan

+0

@nathan Any/AnyObject不符合Codable协议,所以这不会真的有所帮助。 –

我相当确定你的情况类似于我最近发布的问题: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

我与编码的JSON数组像你这样的异构数据的API时,但即使是为了列之前不知道:(

一般来说,我强烈建议不要将数据存储在异构数组中。您将很快忘记哪个索引代表什么属性,更不用说常量会返回一个前进。相反,当你从数组中解码时,建立一个数据模型来存储它。

另一件需要注意的事情是,你的日期不是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)