Разбор ответа JSON с вложенным "в Swift - PullRequest
0 голосов
/ 20 сентября 2018

Я хотел бы узнать, как лучше всего проанализировать ответ json нижеуказанного типа в Swift 4. Ответ задан в двойном коде -

\ "[{\\" value \\ ": \\" Международный университет \ "\\\ "MITSO \\\\" \\ ", \\" id \\ ": \\" a1v24000000uOrPAAU \\ ", \\" addlFields \\ ": [\\" Mi? Народный университет \\\\"MITSO \\\\" \\ "]}] \"

Вот данные в формате NSData -

(String) $ R0 = "data: Необязательно (146 байт) какNSData: <225b7b5c 2276616c 75655c22 3a5c2249 6e746572 6e617469 6f6e616c 20556e69 76657273 69747920 5c5c5c22 4d495453 4f5c5c5c 225c222c 5c226964 5c223a5c 22613176 32343030 30303030 754f7250 4141555c 222c5c22 6164646c 4669656c 64735c22 3a5b5c22 4d693f6e 61726f64 6e792055 6e697665 72736974 6574205c 5c5c224d 4954534f 5c5c5c22 5c225d7d 5d22>»

1008 * Как вамсм. значение ключа "value" имеет внутренние двойные кавычки ("). JSONSerialization считают это недействительным Json. Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

@ OOPer спасибо за решение.Я ценю то, что вы уделяете время.Решение сработало, как и ожидалось.Вставьте здесь код, который может помочь другим.

Вот как я делаю -

func getData(text:String, callback:@escaping (_ result: Array<somedata>?,_ error:Error?) -> Void) {

    let params = ["search":text]

    getDataSomeAPI(url: "http:\\xyz.com\fdf", params: params) { (result, error) in
        if error == nil {
            do {
                //Response is double encoded
                if let firstDecoded = try JSONSerialization.jsonObject(with: result as! Data, options: .allowFragments) as? String
                {
                    let firstDecodedData = firstDecoded.data(using: .utf8)!
                    if let secondDecoded = try JSONSerialization.jsonObject(with: firstDecodedData) as? NSArray {

                        var array =  [somedata]()
                        for obj in secondDecoded {
                            Mapper<somedata>().map(JSONObject: obj).then { mappedObj in
                                array.append(mappedObj)
                            }
                        }
                        callback(array,nil)
                    }
                }
            }
            catch  {
                //Handle unexpected data format
                let error = NSError(domain: "",
                                    code: 0,
                                    userInfo: nil)
                let sErr = Error(err: error)
                callback(nil, sErr)
            }
        } else {
            callback(nil, error)
        }
    }
}
0 голосов
/ 20 сентября 2018

Содержимое ваших данных в виде строки выглядит следующим образом:

"[{\"value\":\"International University \\\"MITSO\\\"\",\"id\":\"a1v24000000uOrPAAU\",\"addlFields\":[\"Mi?narodny Universitet \\\"MITSO\\\"\"]}]"

Просмотр фактического содержимого без дополнительных двойных кавычек и обратной косой черты, необходимых для отображения строки в виде строкового литерала,похоже, что какой-то действительный JSON встроен в строку.

Это может произойти, когда код на стороне сервера дважды кодирует данные.Вам лучше сообщить своему инженеру на стороне сервера, чтобы устранить проблему, но если это сложно или займет много времени, вы можете дважды декодировать его.

Код тестирования:

import Foundation

let dataStr = "<225b7b5c 2276616c 75655c22 3a5c2249 6e746572 6e617469 6f6e616c 20556e69 76657273 69747920 5c5c5c22 4d495453 4f5c5c5c 225c222c 5c226964 5c223a5c 22613176 32343030 30303030 754f7250 4141555c 222c5c22 6164646c 4669656c 64735c22 3a5b5c22 4d693f6e 61726f64 6e792055 6e697665 72736974 6574205c 5c5c224d 4954534f 5c5c5c22 5c225d7d 5d22>".dropFirst().dropLast().replacingOccurrences(of: " ", with: "")
let byteArr = stride(from: 0, to: dataStr.count, by: 2).map{(index: Int)->UInt8 in
    let start = dataStr.index(dataStr.startIndex, offsetBy: index)
    let end = dataStr.index(start, offsetBy: 2)
    return UInt8(dataStr[start..<end], radix: 16)!
}
let responseData = Data(bytes: byteArr)
print(responseData as NSData)

Проверказдесь, является ли вывод оператора print точно таким же, как ваш пример ответа.(Если вы хотите проверить следующий код с вашими фактическими данными, а не с примером ответа, используйте просто let responseData = result as! Data вместо строк выше).

Итак, вам просто нужно использовать JSONSerialization дважды:

block: do {
    let firstDecoded = try JSONSerialization.jsonObject(with: responseData, options: .allowFragments) as! String
    let firstDecodedData = firstDecoded.data(using: .utf8)!
    let secondDecoded = try JSONSerialization.jsonObject(with: firstDecodedData)
    //Code below is an example of using decoded result.
    guard let resultArray = secondDecoded as? [[String: Any]] else {
        print("result is not an Array of Dictionary")
        break block
    }
    print(resultArray)
    if
        let addlFields = resultArray[0]["addlFields"] as? [String],
        let firstAddl = addlFields.first
    {
        print(firstAddl)
    }
} catch {
    print(error)
}

Выходы: (пропуская некоторый вывод для print(responseData as NSData).)

[["id": a1v24000000uOrPAAU, "value": International University "MITSO", "addlFields": <__NSSingleObjectArrayI 0x100e40c80>(
Mi?narodny Universitet "MITSO"
)
]]
Mi?narodny Universitet "MITSO"

(Вы можете найти некоторые части, такие как <__NSSingleObjectArrayI 0x100e40c80>, странные, но это просто проблемасоздания описания по умолчанию, и вы можете получить доступ к элементам в виде массива.)


В любом случае, пожалуйста, попробуйте и посмотрите, что вы можете получить с моим кодом выше.

...