Parsing only few of the fields in json

94 Views Asked by At

I am trying to parse following json:

"{\"action\":\"question-answered\",\"data\":{\"type\":\"agreement\",\"questionType\":{},\"answer\":{}}}"

with following model:

    struct SymptomCheckerResult: Codable {
    let action: String?
    
    enum CodingKeys: String, CodingKey {
        case action = "action"
    }
}

I just require value from one key. But my parsing is failing with following error message:

typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found a string/data instead.", underlyingError: nil))

Following is my parsing code:

let jsonData = Data(messageBody.utf8)
    do {
        let symptomCheckerResult = try JSONDecoder().decode(SymptomCheckerResult.self, from: jsonData)
        print(symptomCheckerResult)
    } catch (let error) {
        print(error)
    }

I could have a very long json but I just need values from 1 key but my parsing is always failing. It looks very simple but somehow it is not working for me. Can someone please help me point my mistake?

2

There are 2 best solutions below

0
Larme On BEST ANSWER

You have JSON Stringified: Your JSON is a JSON String, it starts with a double quotes. It's not direct JSON.

If we needed to declare your answer in Swift, it could be:

let messageBody = """
"{\\\"action\\\":\\\"question-answered\\\",\\\"data\\\":{\\\"type\\\":\\\"agreement\\\",\\\"questionType\\\":{},\\\"answer\\\":{}}}"
"""

There are actually backslash, it's not the Console that print them because of debugging tools.

So you need to serialize it first:

let jsonStr = try JSONDecoder().decoder(String.self, from: jsonData)
let symptomCheckerResult = try JSONDecoder().decode(SymptomCheckerResult.self, from: Data(jsonStr.utf8)
3
Dzmitry Sotnikov On

Try the SwiftyJSON library, which is convenient (at least for me). It lets you work with JSON quite flexibly. https://github.com/SwiftyJSON/SwiftyJSON

In this case the code will look like this.

  1. Get JSON from string or data.
  2. Get the typed value of the desired field.

If there is no such parameter in JSON it will return nil.

let json = JSON(data: data)
let actionValue = json["action"].string