如何在Swift 4中保证有效的JSON?

时间:2018-04-29 16:19:36

标签: json swift

我正在尝试使用从服务返回的JSON数据。根据JSON验证器,JSON是有效且非常简单的:

[{"ID":"SDS-T589863","TotalRisk":0.2458,"TotalScore":641.032}] 

然而,试图在我的Swift 4代码中解析它,这是神秘的(至少对我来说)无效。这是我尝试解析它:

 // make the request
    let task = session.dataTask(with: urlRequest) {
        (data, response, error) in
        // check for any errors
        guard error == nil else {
            print(error!)
            return
        }
        // make sure we got data
        guard let responseData = data else {
            print("Error: did not receive data")
            return
        }

        // this is fine:
        guard let ddd = String(bytes: responseData, encoding: String.Encoding.utf8) else {
            print("can't")
            return
        }

        print(ddd) // prints [{"ID":"SDS-T589863","TotalRisk":0.2458,"TotalScore":641.032}] happily

        do {
            // cannot serialize
            guard let risk = try JSONSerialization.jsonObject(with: responseData, options: [JSONSerialization.ReadingOptions.allowFragments])
                as? [String: Any]
            else {
                    print("error trying to convert data to JSON")
                    return
            }
            print(risk)
        } catch  {
            print("error trying to convert data to JSON")
            return
            }
        }
    task.resume()

}

假设我无法控制JSON对象或它返回给我的格式,有没有办法告诉JSON有什么问题,并且可能格式化响应以便可以正确序列化? / p>

2 个答案:

答案 0 :(得分:4)

您应该将数据转换为[[String: Any]]类型,因为您有响应数组。

您正在尝试转换为[String: Any],但您有一个[String: Any]数组,因为您的回复位于[]括号中。

示例:

let risk = try JSONSerialization.jsonObject(with: responseData, options: [JSONSerialization.ReadingOptions.allowFragments]) as? [[String: Any]]

或者如果您只想从响应中获取一个[String: Any]对象,您可以写:

let risk = (try JSONSerialization.jsonObject(with: responseData, options: [JSONSerialization.ReadingOptions.allowFragments]) as? [[String: Any]])?.first

或者如果你的对象可以是数组而不是数组(但听起来有点奇怪),你可以尝试转换为几种可能的类型。

答案 1 :(得分:1)

响应类型是json对象的数组,因此您必须将其强制转换为[[String: Any]]。由于您使用的是Swift 4,因此可以使用Decodable类型将模型映射到响应。

     let task = URLSession().dataTask(with: urlRequest) { (data, response, error) in
        // check for any errors
        guard error == nil else {
            print(error!)
            return
        }
        // make sure we got data
        guard let responseData = data else {
            print("Error: did not receive data")
            return
        }

        do {
            let decoder = JSONDecoder()
            let riskArray = try decoder.decode([Risk].self, from: responseData)
            print(riskArray)
        } catch {
            print("error trying to convert data to Model")
            print(error.localizedDescription)
        }
    }
    task.resume()

您可以将模型结构定义为

struct Risk: Decodable {
    let id: String
    let totalRisk: Double
    let totalScore: Double

    enum CodingKeys: String, CodingKey {
        case id = "ID"
        case totalRisk = "TotalRisk"
        case totalScore = "TotalScore"
    }
}

您可以阅读有关可解码协议here

的更多信息