将字符串形式的JSON转换为Swift对象或JSON字典

3

在我的Swift代码中,我向我的node.js服务器发出一个URLRequest

URLSession.shared.dataTask(with: checkoutRequest, completionHandler: {
    [weak self] (data: Data?, response: URLResponse?, error: Error?) in
    guard let data = data,
        let dataString = String(data: data, encoding: String.Encoding.utf8) else {
            return
    }

    // Help me!!!

}).resume()

Node.js通过使用Braintree Payments的结帐API处理此请求中的交易。

checkoutProcessor.processCheckout(amount, nonce, (error, result) => {
    // Checkout callback
    if (error) {
        res.write(error.message)
        res.end()
    } else if (result) {
        console.log(result)
        res.write(JSON.stringify(result))
        res.end()
    }
})

通常情况下,如果API请求失败(例如没有信号),它会返回一个error,但是如果交易成功,则会返回一个result

然而,result的类型取决于财务交易是否成功:

例如,成功交易的result

Object {transaction: Transaction, success: true}

失败交易的结果

ErrorResponse {errors: ValidationErrorsCollection, params: Object, message: "Insufficient Funds", transaction: Transaction, success: false}
< p > dataString最终看起来像这样:

{\"transaction\":{\"id\":\"m7mj3qd7\",\"status\":\"submitted_for_settlement\",\"type\":\"sale\",\"currencyIsoCode\":\"USD\",\"amount\":\"12.34\",\"merchantAccountId\":\"yourpianobar\",\"subMerchantAccountId\":null,\"masterMerchantAccountId\":null,\"orderId\":null,\"createdAt\":\"2018-09-19T03:30:27Z\",\"updatedAt\":\"2018-09-19T03:30:27Z\",\"customer\":{\"id\":\"622865439\",\"firstName\":\"Test\",\"lastName\":\"FromSwiftTest\"

它确实类似于JSON对象,但我似乎无法使用JSONDecoder解码它,这样做会失败。(JSONEncoder也失败了)

我看到的大多数将字符串化的JSON数据转换为Swift对象的解决方案都涉及编写Swiftstruct,以便将所有JSON对象的属性塞进去,但由于Swift端的结果数据结构是未知的,所以我不知道该怎么办。

如何将这些对象导入我的Swift代码中?

注意:我也尝试在node.js代码中仅发送res.send(result),但这并没有真正改变任何内容。


为什么你不能将 ErrorResponse 也转换成字符串呢?这个应该是由 API 返回的。 - Stephen O'Connor
“Object”和“ErrorResponse”是否是字符串化输出的一部分?你展示交易结果的方式有点令人困惑。你能澄清一下吗? - Mike Taverne
@MikeTaverne 我已经编辑了帖子,希望更清楚明白一些。 - Jonathan Tuzman
@SteveO'Connor 无论是 Object 还是 ErrorResponseresult 都会被转化为字符串。 - Jonathan Tuzman
如果result被字符串化,那么它应该在Swift中以字典的形式结束。不确定你在问什么。 - Stephen O'Connor
2个回答

2
这对于Swift 5来说是可行的解决方案:
    if let data = dataString.data(using: String.Encoding.utf8) {
        do {
            if let dictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] {
                // Use this dictionary
                print(dictionary)
            }
        } catch _ {
            // Do nothing
        }
    }

0
您可以使用JSONSerialization类将数据从数据转换为基于您的JSON响应的字典/数组。在Swift 4中,代码可能看起来像下面这样(根据我的理解):
URLSession.shared.dataTask(with: checkoutRequest) { (data, response, error) in
                guard let requestData = data, error == nil, let httpResponse = response as? HTTPURLResponse else {
                    // handle error
                    return
                }
                do {
                    if httpResponse.statusCode == 200 {
                        // success json
                        let jsonObject = try JSONSerialization.jsonObject(with: requestData, options: .allowFragments)
                        print(jsonObject) // jsonObject can be dictionary or Array. Typecast it based on your response
                    } else {
                        //error json
                        let jsonObject = try JSONSerialization.jsonObject(with: requestData, options: .allowFragments)
                        print(jsonObject) // jsonObject can be dictionary or Array. Typecast it based on your response
                    }
                }
                catch {
                    print(error.localizedDescription)
                }
            }.resume()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接