1

I am receiving a response something like this in some key eg:

"abc" : "[{\"ischeck\":true,\"type\":\"Some type\"},{\"ischeck\":false,\"type\":\"other type\"}]"]"

I need to convert this into normal array. i am using this following function for this.

[{"ischeck": true, "type":"Some type"},{"ischeck": true, "type":"other type"}]
func fromJSON(string: String) throws -> [[String: Any]] {
    let data = string.data(using: .utf8)!
    guard let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [AnyObject] else {
        throw NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid JSON"])
    }
      //swiftlint:disable:next force_cast
    return jsonObject.map { $0 as! [String: Any] }
}
2
  • Use codable: swiftbysundell.com/basics/codable Commented Sep 11, 2019 at 8:53
  • @JoakimDanielson The value for key abc is another JSON string, not an array Commented Sep 11, 2019 at 9:01

1 Answer 1

1

You have to call JSONSerialization.jsonObject twice. First to deserialize the root object and then to deserialize the JSON string for key abc.

func fromJSON(string: String) throws -> [[String: Any]] {
    let data = Data(string.utf8)
    guard let rootObject = try JSONSerialization.jsonObject(with: data) as? [String:String],
        let innerJSON = rootObject["abc"]  else {
            throw NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid JSON"])
    }
    let innerData = Data(innerJSON.utf8)
    guard let innerObject = try JSONSerialization.jsonObject(with: innerData) as? [[String:Any]] else {
        throw NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid JSON"])
    }
    return innerObject
}

Another more comfortable approach is to decode the string with Decodable

let jsonString = """
{"abc":"[{\\"ischeck\\":true,\\"type\\":\\"Some type\\"},{\\"ischeck\\":false,\\"type\\":\\"other type\\"}]"}
"""

struct Root : Decodable {
    let abc : [Item]

    private enum CodingKeys : String, CodingKey { case abc }

    init(from decoder : Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let abcString = try container.decode(String.self, forKey: .abc)
        abc = try JSONDecoder().decode([Item].self, from: Data(abcString.utf8))
    }
}

struct Item : Decodable {
    let ischeck : Bool
    let type : String
}

do {
   let result = try JSONDecoder().decode(Root.self, from: Data(jsonString.utf8))
   print(result.abc) 
} catch {
    print(error)
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.