快速删除 JSON 中的部分以对其进行解码

问题描述 投票:0回答:1

我将此作为 API 的响应

{
  "AAPL": {
    "quote": {
      "symbol": "AAPL",
      "companyName": "Apple Inc.",
      "sector": "Technology"
    }
  },
  "FB": {
    "quote": {
      "symbol": "FB",
      "companyName": "Facebook Inc.",
      "sector": "Technology"
    }
  }
*... lots of stocks*
}

如何将其转换为这个? (稍后解码)

[
  {
    "symbol": "AAPL",
    "companyName": "Apple Inc.",
    "sector": "Technology"
  },
  {
    "symbol": "FB",
    "companyName": "Facebook Inc.",
    "sector": "Technology"
  }
*... lots of stocks*
]

不只是AAPL或FB,我需要大量“记录”的最佳答案

json swift decode
1个回答
0
投票

所以问题实际上不是改变结构而是解码 json。我认为最好的方法是将其变成标准形式。但我错了。我发现了一篇名为“Decode and Flatten JSON with Dynamic Keys using Decodable”的文章。这解决了我的问题!

{
  "S001": {
    "firstName": "Tony",
    "lastName": "Stark"
  },
  "S002": {
    "firstName": "Peter",
    "lastName": "Parker"
  },
  "S003": {
    "firstName": "Bruce",
    "lastName": "Wayne"
  }
}

struct DecodedArray: Decodable {

    var array: [Student]
    
    // Define DynamicCodingKeys type needed for creating
    // decoding container from JSONDecoder
    private struct DynamicCodingKeys: CodingKey {

        // Use for string-keyed dictionary
        var stringValue: String
        init?(stringValue: String) {
            self.stringValue = stringValue
        }

        // Use for integer-keyed dictionary
        var intValue: Int?
        init?(intValue: Int) {
            // We are not using this, thus just return nil
            return nil
        }
    }

    init(from decoder: Decoder) throws {

        // 1
        // Create a decoding container using DynamicCodingKeys
        // The container will contain all the JSON first level key
        let container = try decoder.container(keyedBy: DynamicCodingKeys.self)

        var tempArray = [Student]()

        // 2
        // Loop through each key (student ID) in container
        for key in container.allKeys {

            // Decode Student using key & keep decoded Student object in tempArray
            let decodedObject = try container.decode(Student.self, forKey: DynamicCodingKeys(stringValue: key.stringValue)!)
            tempArray.append(decodedObject)
        }

        // 3
        // Finish decoding all Student objects. Thus assign tempArray to array.
        array = tempArray
    }
}

struct Student: Decodable {

    let firstName: String
    let lastName: String

    // 1
    // Define student ID
    let studentId: String

    // 2
    // Define coding key for decoding use
    enum CodingKeys: CodingKey {
        case firstName
        case lastName
    }

    init(from decoder: Decoder) throws {

        let container = try decoder.container(keyedBy: CodingKeys.self)

        // 3
        // Decode firstName & lastName
        firstName = try container.decode(String.self, forKey: CodingKeys.firstName)
        lastName = try container.decode(String.self, forKey: CodingKeys.lastName)

        // 4
        // Extract studentId from coding path
        studentId = container.codingPath.first!.stringValue
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.