Stringified JSON to Swift Object or JSON dictionary

Viewed 1412

In my Swift code I make a URLRequest to my node.js server:

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()

The node.js handles this request by processing a transaction through the Braintree Payments checkout 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()
    }
})

As usual, if the API request fails (e.g., no signal) it returns an error but if the transaction goes through, it returns a result.

The type of the result, however, depends on whether the financial transaction fails or succeeds:

For example, the result for a successful transaction:

Object {transaction: Transaction, success: true}

result for failed transaction:

ErrorResponse {errors: ValidationErrorsCollection, params: Object, message: "Insufficient Funds", transaction: Transaction, success: false}

The dataString winds up looking like this:

{\"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\"

which certainly resembles a JSON object but I can't seem to decode it with JSONDecoder, doing so fails. (JSONEncoder also fails)

Most solutions I see for Objectifying stringified JSON data into Swift involves writing a swift struct into which to plop all the JSON object's properties, but since this the data structure of the result is unknown on the swift end, I don't know what to do.

How do I get these objects into my swift code?

Note: I've also tried just sending res.send(result) in the node.js code but that doesn't really change anything.

2 Answers

This would do the trick for 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
        }
    }

You can use JSONSerialization class on your data to convert it from data to Dictionary/Array based on your json response. The code can look something like below (based on my understanding) in 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()
Related