Декодируйте файл JSON,содержащий строковые ключи, каждый из которых содержит одну пару значений ключа, в [(Дата, двойной)]

#arrays #json #swift #jsondecoder

Вопрос:

Я пытаюсь определить,как читать файл JSON, состоящий из серии строк, под каждой из которых находится одна пара значений ключа в [(Дата, двойной)]. Я смог сделать это,вручную добавив основной ключ «Временные ряды (ежедневно)» в верхнюю часть файла JSON, а структуры ниже возвращают [(Дата, дважды)]. Я хотел бы иметь возможность исключить шаг добавления «Временных рядов (ежедневно)» в файл JSON,но все равно возвращать [(Дата, дважды)]. Мы будем признательны за любое представление о том, как достичь этих результатов.

 {
    "Time Series (Daily)": { // this entire line is manually added to JSON file
        "20200803": {
            "NAV": 173.94769
        },
        "20200804": {
            "NAV": 174.57441
        },

struct PrincipalTimeSeriesData {

    var timeSeriesDaily: [(Date, Double)]
}

extension PrincipalTimeSeriesData: Decodable {
    
    enum CodingKeys: String, CodingKey {
        case timeSeriesDaily = "Time Series (Daily)"
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        timeSeriesDaily = try container
                .decode([String:PrincipalTimeSeriesDaily].self, forKey: .timeSeriesDaily)
                .map { (dateFormatterPrin.date(from: $0)!, $1.close) }
    }
}

struct PrincipalTimeSeriesDaily {

    let close: Double
    
}

extension PrincipalTimeSeriesDaily: Decodable {

    enum CodingKeys: String, CodingKey {
        case close = "NAV"
    }
}
 

Ответ №1:

Вы можете декодировать данные как [String:PrincipalTimeSeriesDaily] , а затем сопоставить ключи/значения полученного словаря в желаемом формате:

 let jsonData = """
{
        "20200803": {
            "NAV": 173.94769
        },
        "20200804": {
            "NAV": 174.57441
        },
}
""".data(using: .utf8)!

let dateFormatterPrin = DateFormatter()
dateFormatterPrin.dateFormat = "yyyyMMdd"


struct PrincipalTimeSeriesDaily {

    let close: Double
    
}

extension PrincipalTimeSeriesDaily: Decodable {

    enum CodingKeys: String, CodingKey {
        case close = "NAV"
    }
}

do {
    let decoded = try JSONDecoder().decode([String:PrincipalTimeSeriesDaily].self, from: jsonData)
    let converedToDateKeysArray = decoded.map { item -> (Date,Double) in
        (dateFormatterPrin.date(from: item.key)!,item.value.close)
    }.sorted { $0.0 < $1.0 }
    print(converedToDateKeysArray)
} catch {
    print(error)
}
 

Комментарии:

1. Я использую self.convertedToDateArray = self.convertedToDateArray.сортировка { $0.0 Он работал в исходном коде, но теперь не работает. Как ты думаешь, почему это так?

2. Я добавил рабочий пример этого в свой код-кажется, он работает нормально.

3. Спасибо. Мы ценим вашу помощь.

4. Без проблем. Если ответ был полезным, пожалуйста, не стесняйтесь его озвучивать.

5. Обычно ли лучше деокодировать, а затем сопоставлять, как у вас, вместо того, чтобы пытаться использовать структуры и их инициалы для декодирования и сопоставления/преобразования?