2017-08-16 14 views
2

Ich habe einige JSON, die in folgendem Format kommt zurückSwift Dekodierbare JSON Wörterbuch mit heterogener Array

{ 
"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 
    ] 
] 
} 

Das Problem ist, dass der ‚Schlüssel‘ anders sein wird jedes Mal, und der ‚Wert‘ ein heterogenes enthalten Array von Strings (die in Daten konvertiert werden sollen) und Ints.

Gibt es eine Möglichkeit, das Decodable-Protokoll von Swift zu verwenden, um daraus Objekte zu machen?

Hier ist eine Struktur, die es als, decodiert werden konnte

struct MyJSONData: Decodable { 

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

Wenn jedoch gibt es einen besseren Weg, um die Struktur zu strukturieren, Im alle Ohren!

Vielen Dank im Voraus.

+0

Sie keine/ANYOBJECT verwenden können. Ist Ihre Datenstruktur stabil? Ich meine, wird es immer ein String und ein Int in dieser Reihenfolge sein? – nathan

+0

@nathan Any/AnyObject entsprechen nicht dem Codable-Protokoll, so dass es nicht wirklich helfen wird. –

Antwort

1

Ich bin mir ziemlich sicher, dass Ihr Fall einer Frage ähnlich ist, die ich vor kurzem gepostet habe: Flattening JSON when keys are known only at runtime.

Wenn ja, könnten Sie die folgende Lösung verwenden:

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 

Arbeitslösung: http://swift.sandbox.bluemix.net/#/repl/59949d74677f2b7ec84046c8

1

Ich war mit einer API arbeiten, die wie das Ihre mit heterogenen Daten JSON-Array codiert, sondern auch die Reihenfolge der die Spalten war vorher nicht bekannt Hand :(

Im Allgemeinen empfehle ich dringend, Daten in heterogenen Arrays zu speichern. Sie werden sehr schnell vergessen, welcher Index für welche Eigenschaft steht, ganz zu schweigen von der konstanten Rückübertragung nd her. Erstellen Sie stattdessen ein Datenmodell, um es beim Dekodieren aus dem Array zu speichern.

Eine andere Sache zu beachten ist, dass Ihr Datum ist nicht, was JSONDecoder standardmäßig erwartet. Es erwartet das ISO 8601-Format (yyyy-MM-ddTHH:mm:ssZ), während die Zeitkomponente in Ihrer Datumszeichenfolge fehlt. Sie können sagen, was JSONDecoderDateFormatter indem ein Brauch zu tun:

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)