1

I am using SwiftyJson library for parsing my following json

{
    "data": {
        "id": "12345",
        "messages": {
            "message": "{\"data\":{\"msg\":\"HelloMsg\"}}"
        }
    }
}

I tried to use following code to get msg parameter

let json = JSON(data)
let msg = JSON(json["data"]["messages"]["message"])
msg["data"]["msg"].stringValue

However, I could not get the value of msg parameter. What shall I do to get HelloMsg?

atalayasa
  • 3,310
  • 25
  • 42

4 Answers4

4

The content of the "message" field is not parsed JSON, it's a JSON string.

Use SwiftyJSON's JSON(parseJSON:) initializer to accept a string as input and parse it as JSON:

let messages = json["data"]["messages"]["message"].stringValue
let innerJSON = JSON(parseJSON: messages)
let msg = innerJSON["data"]["msg"].stringValue // "HelloMsg"
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
2

The error occurs because JSON(...) is the wrong API to initialize and parse a SwiftyJSON object from a string.

You have to use this syntax:

let json = JSON(data)
let msg = JSON(parseJSON: json["data"]["messages"]["message"].stringValue)
msg["data"]["msg"].stringValue

From the documentation of init(_ object: Any):

note: this does not parse a String into JSON, instead use init(parseJSON: String)


Edit:

To test the code in a Playground

let str = """
{"data": {"id": "12345",
            "messages": {
            "message": "{\\"data\\":{\\"msg\\":\\"HelloMsg\\"}}"
        }
    }
}
"""

let data = Data(str.utf8)
let json = JSON(data)
let msg = JSON(parseJSON: json["data"]["messages"]["message"].stringValue)
msg["data"]["msg"].stringValue

The JSON as traditional literal string is

let str = "{\"data\": {\"id\": \"12345\",\"messages\": {\"message\": \"{\\\"data\\\":{\\\"msg\\\":\\\"HelloMsg\\\"}}\"}}}"
vadian
  • 274,689
  • 30
  • 353
  • 361
  • lol this time I decided to answer because I didn't see your answer, as I usually see yours first and so I usually don't need to do it... but now here it is! ahah :D – Eric Aya Feb 16 '18 at 14:33
  • if I use `let msg : String = "{\"data\":{\"msg\":\"HelloMsg\"}}" let jsonFromString = JSON(parseJSON:msg) debugPrint(jsonFromString["data"]["msg"].stringValue)` I am giving "" printed out – Reinier Melian Feb 16 '18 at 14:39
  • @ReinierMelian I have made the same solution as vadian, it works. I even tested in a Playground with OP's exact source text pasted in a file. – Eric Aya Feb 16 '18 at 14:42
  • @Moritz yes but what I am doing wrong then?, I am trying to learn from – Reinier Melian Feb 16 '18 at 14:42
  • @ReinierMelian No idea. Here's a screenshot of my test: https://imgur.com/bALDRQY – Eric Aya Feb 16 '18 at 14:52
  • its weird works for your file but to for String declared? @Moritz – Reinier Melian Feb 16 '18 at 14:57
  • @ReinierMelian I think you will get same result as we do if you double escape the quotes in your string literal – Eric Aya Feb 16 '18 at 14:58
  • Same result @Moritz with `"\"{\"data\":{\"msg\":\"HelloMsg\"}}\""` – Reinier Melian Feb 16 '18 at 15:03
  • @ReinierMelian If you use Swift 4's literal string syntax it must be "{\\"data\\":{\\"msg\\":\\"HelloMsg\\"}}" because you have to escape the backslashes themselves. – vadian Feb 16 '18 at 15:09
  • "{\\"data\\":{\\"msg\\":\\"HelloMsg\\"}}" show a compilation error for me @vadian – Reinier Melian Feb 16 '18 at 15:14
  • @ReinierMelian Maybe a misunderstanding. I mean the literal syntax let foo = `""" ...text... """`. The syntax with double backslashes is supposed to work. I updated the answer with code to be pasted directly into a Playground. – vadian Feb 16 '18 at 15:19
  • forget about it, I can't make it work, but anyway thanks, if you can please post this example using a string variable to see how it works, I will upvote your answer @vadian – Reinier Melian Feb 16 '18 at 15:26
  • @ReinierMelian I added the traditional literal string syntax. – vadian Feb 16 '18 at 15:28
1

The messaage is a string. not a JSON. so SwiftyJson could not parse it. You will have to first parse that string and than get the message from that using JSONSerialization.jsonObject(with: Data, options: JSONSerialization.ReadingOptions).

You can refer to this answer to get the dictionary from that string: https://stackoverflow.com/a/30480777/7820107

hardik parmar
  • 853
  • 8
  • 15
1

Your second "message" key value is a String with a dictionary in JSON format, so you need to convert that string to JSON and access to ["data"]["msg"] then

Code

let json = JSON(data)
let msg = json["data"]["messages"]["message"]
let jsonFromString = JSON(data: msg.data(using: .utf8)!, options: JSONSerialization.ReadingOptions.allowFragments, error: nil)
debugPrint(jsonFromString["data"]["msg"])

Output

HelloMsg
Reinier Melian
  • 20,519
  • 3
  • 38
  • 55