如何使用SwiftyJSON解析具有歧义类型的数据?

问题描述

我的JSON结构如下:

{
  "data": [
    {
      "value":["val1","val2","val3"]
    },{
      "value":"val"
    }
  ]
}

那么我将如何在此处解析“值”字段?有时它是一个字符串数组,有时它只是一个字符串。我将为它分配什么类型?

解决方法

使用SwiftyJSON,您可以检查value属性的值是简单字符串还是字符串数组,如下所示:

let jsonString = """
{
  "data": [
    {
      "value":["val1","val2","val3"]
    },{
      "value":"val"
    }
  ]
}
"""
let json = JSON(parseJSON: jsonString)

json["data"].array?.forEach { dataItem in
    if let dataArray = dataItem["value"].array {
        print("array: \(dataArray)")
        print("array first item: \(dataArray.first?.string ?? "nil")")
    } else if let dataString = dataItem["value"].string {
        print("string: \(dataString)")
    }
}
,

您需要以某种方式抽象数据数组中的字典值。然后,在访问对象时,可以对它们进行类型检查,或者在解码时进行类型检查。

这是我使用本地JSONDecoder解决此问题的方法。重要的是您需要为解码器提供严格的对象类型。 Any,AnyObject类不符合Decoder协议,因为它们没有要解码的类型容器。

enum B: Decodable {
    
    private enum CodingKeys: CodingKey {
        case value
    }
    
    enum BDecodingError: Error {
        case decoding(String)
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        if let val = try? container.decodeIfPresent(Array<String>.self,forKey: .value) {
            self = .array(val)
            return
        }
        if let val = try? container.decodeIfPresent(String.self,forKey: .value) {
            self = .string(val)
            return
        }
        
        throw BDecodingError.decoding("B Decoding Error")
    }
    
    case array(Array<String>)
    case string(String)
}

B枚举负责将对象保留在字典中。您可以在此处指定可能的类型,然后检查对该类型的解码是否成功。

struct A: Decodable {
    let data: [B]
}

结构只是将字典的对象保存在data数组中。