简体   繁体   English

检查 json 响应是数组还是整数或字符串作为键?

[英]check the json response is array or int or string for a key?

I am having the json response in which "products" key sometime having the int value and some cases it had an array?我有 json 响应,其中“产品”键有时具有 int 值,在某些情况下它有一个数组? How to check whether it is having array or Int?如何检查它是否具有数组或 Int?

"products": 25

or或者

"products": [77,80,81,86]

I am using this我正在使用这个

self.productsCount = mResp["products"] as! [Int]

but it is crashed every time when it is not having array.但是每次没有数组时它都会崩溃。

Now i am not getting how to check this because i have the different option for Int and Array?现在我不知道如何检查这个,因为我有不同的 Int 和 Array 选项?

Please help me.Thanks请帮助我。谢谢

It crashes because you force unwrap as an Integer Array, even though you just have an integer.它崩溃是因为你强制解包为一个整数数组,即使你只有一个整数。 The solution is to check for both:解决方案是检查两者:

self.productsCount = mResp["products"] as? [Int] ?? mResp["products"] as? Int

Other Solution其他解决方案

if let proCount = mResp["products"] as? [Int] { 
  self.productsCount = proCount
} else {
  self.productsCount = mResp["products"] as? Int
}

There is no need to fall back to Any here.这里没有必要回退到Any Even problematic JSON like this can be handled with Codable .甚至像这样有问题的 JSON 也可以使用Codable处理。 You just need to keep trying the different types until one works.您只需要继续尝试不同的类型,直到其中一种有效。

struct Thing: Decodable {
    let products: [Int]

    enum CodingKeys: String, CodingKey {
        case products
    }

    init(from decoder: Decoder) throws {
        // First pull out the "products" key
        let container = try decoder.container(keyedBy: CodingKeys.self)

        do {
            // Then try to decode the value as an array
            products = try container.decode([Int].self, forKey: .products)
        } catch {
            // If that didn't work, try to decode it as a single value
            products = [try container.decode(Int.self, forKey: .products)]
        }
    }
}


let singleJSON = Data("""
{ "products": 25 }
""".utf8)

let listJSON = Data("""
{ "products": [77,80,81,86] }
""".utf8)

let decoder = JSONDecoder()

try! decoder.decode(Thing.self, from: singleJSON).products   // [25]
try! decoder.decode(Thing.self, from: listJSON).products     // [77, 80, 81, 86]

This is temporary solution as you want.这是您想要的临时解决方案。 Check for possible type with "Any" type.使用“任何”类型检查可能的类型。

    var anyType : Any!
    anyType = "123"
    anyType = ["Test","Test1"]
    anyType = 1
    if anyType is Array {
        print("is Array")
    }else if anyType is String {
        print("is String")
    }else if anyType is Int {
        print("is Int")
    }

let's assume your json name is jsonData假设您的 json 名称是jsonData

Check for Int and Array Int :检查IntArray Int

if let intVal = jsonData["products"] as? Int {
    print("Products is a Integer: ", intVal)

} else if let jsonArr = jsonData["products"] as? [Int] {

    var intVals = [Int]()
    for json in jsonArr {
        intVals.append(json)
    }
    print("Json is array of Int: ", intVals)
}
let dict = [77,80,81,86]//Pass your parameter or parsed json value
 if dict is Array<Any> {
    print("Yes, it's an Array")
}
else{
      print("NO, it's not an Array")

}

Generic solution would be like this,通用解决方案是这样的,

let products = mResp["products"] as? Any
if let item = products as? [Int] {
    print("array", item)
} else if let item = products as? Int {
    print("Integer", item)
}

Use Generics for obtaining a better solution and provide the type at the time of decoding this model.使用Generics以获得更好的解决方案并在解码此模型时提供类型。

struct Product<T: Codable>: Codable {
    let products: T?
}

And you can use it with nested try catch :您可以将它与嵌套的try catch一起使用:

do {
    let product = try JSONDecoder().decode(Product<Int>.self, from: data)
    print(product)
} catch {
    do {
        let product = try JSONDecoder().decode(Product<[Int]>.self, from: data)
        print(product)
    } catch {
        print(error)
    }
}

Note: This solution assumes there is not more than a few different type-varying properties in the codable struct.注意:此解决方案假定可编码结构中不超过几个不同的类型变化属性。 If there are multiple type-varying properties I'd recommend use a custom init(decoder:) as provided in the accepted answer which would be much better design instead of having a try-catch tree.如果有多个类型不同的属性,我建议使用接受的答案中提供的自定义init(decoder:) ,这将是更好的设计,而不是使用try-catch树。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM