2017-08-16 50 views
2

我有一些的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協議,所以這不會真的有所幫助。 –

回答

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

1

我與編碼的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)