【问题标题】:How to decode array of different data types?如何解码不同数据类型的数组?
【发布时间】:2021-11-14 05:14:36
【问题描述】:

我需要解码一个 JSON:

  override func viewDidLoad() {
    super.viewDidLoad()
    foo()
  }
  
  struct MOCK: Codable {
    var array = [AnyClass]()
    
    enum CodingKeys: String, CodingKey {
            case array = "arr"
        }
  }
  
  func foo() {
    let MOCK_JSON = """
      {
        "arr" : [
            0,"my_str1",
            90,"my_str2"
        ]
      }
"""
    
    do {
      let data: Data = MOCK_JSON.data(using: .utf8)!
      let manifest = try JSONDecoder.init().decode(MOCK.self, from: data)
      
      print("\(manifest)")
      
      
    } catch let error {
      print("ERROR:", error)
    }
  }

这里我使用了一个模拟 JSON,但我使用的真实结构看起来是一样的

我得到的错误是

类型“ViewController.MOCK”不符合协议“Decodable”

如何正确解码 JSON?

UPD

根据@vadian 评论,我尝试像这样使用unKeyedContainer

  struct MOCK: Decodable {
    let array: [Any]
    
    init(from decoder: Decoder) throws {
      var container = try decoder.unkeyedContainer()
      array = try container.decode([Any].self)
    }
  }

但我仍然在最后一行出现错误

对实例方法“解码”的调用没有完全匹配

【问题讨论】:

  • @Cy-4AH 这不是很明显你的意思是什么?在您的示例中,您在我的示例中解码了一个字符串数组(实际上这是一个问题)我正在尝试解码一个不同类型的数组...
  • AnyCodableAnyObjectAnyClass 中均不受支持。您的数组是规则的,并且交替使用 IntString,因此请使用 unKeyedContainer 和循环。
  • 你可以寻找“Any Codable”、“AnyCodable”或“Generic”+ Swift,应该有一些想法......
  • @vadian 为我的问题添加了更新

标签: arrays json swift


【解决方案1】:

CodableAnyObjectAnyClass 不支持Any

一个可能的解决方案是一个unkeyedContainer 和一个带有关联值的枚举

let mockJSON =
    """
    {
        "arr" : [
            0,"my_str1",
            90,"my_str2"
        ]
    }
    """

enum MockType {
    case int(Int), string(String)
}

struct Mock: Decodable {
    
    var values = [MockType]()
    
    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        while !container.isAtEnd {
            do {
                let intValue = try container.decode(Int.self)
                values.append(.int(intValue))
            } catch DecodingError.typeMismatch {
                let stringValue = try container.decode(String.self)
                values.append(.string(stringValue))
            }
        }
    }
}

let data = Data(mockJSON.utf8)

do {
    let decoder = JSONDecoder()
    let result = try decoder.decode([String:Mock].self, from: data)
    print(result["arr"]!.values)
} catch {
    print(error)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-02
    • 2020-04-09
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多