Parsing в Swift


#1

Доброго времени суток, кто сможет подсказать, как распарсить такое?
Либо как можно привести вложенный json к нужно виду?

Вот проблема
https://bugs.swift.org/browse/SR-5552
https://developer.apple.com/forums/thread/83165
Возможно ли как-то решить не меняя ответ с сервера?

Не могу дословную строку кинуть, она тут отображается без слеша

import Foundation

let json = """

{

"customJson": "{\"toto\":{\"type\":\"String\",\"value\":\"toto\",\"id\":\"auQvn_2lj\"}}"

}

"""

let json = try ! JSONSerialization.jsonObject(with: json.data(using: .utf8)!, options: [])

print("json: ", json)

Fatal error: ‘try!’ expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=3840 “Badly formed object around character 23.” UserInfo={NSDebugDescription=Badly formed object around character 23.}: file __lldb_expr_75/test.playground, line 9


#2

Есть вариант: замените \" на \\". Я имею в виду уже на вашей стороне, когда вы получите json.
Я пробовал с ObjectMapper’om

struct Model: Mappable {
    
    var string: String!
    
    init?(map: Map) {}
    
    mutating func mapping(map: Map) {
        string <- map["customJson"]
    }
}

struct Model2: Mappable {
    
    var string2: String!
    
    init?(map: Map) {}
    
    mutating func mapping(map: Map) {
        string2 <- map["key"]
    }
}

let jsonData = """
{"customJson": "{\\"key\\": \\"Test String\\"}"}
"""
print(jsonData)
let model = Model(JSONString: jsonData)
print(model)
let model2 = Model2(JSONString: model?.string ?? "")
print(model2)

#3

Есть проблема, что я не могу сторонние зависимости использовать, я тоже думал о замене текста, но пока не придумал как)


#4

Такая строка:

let json = """
...
"""

Не равна ответу с сервера (нужно два слеша), если json поместить в файл он корректно распарсится:

Сам код:

struct CustomJson: Decodable {
    struct Toto: Decodable {
        let type,
            value,
            id: String
    }
    
    let toto: Toto?
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let data = try container.decode(String.self).data(using: .utf8)!
        toto = try JSONDecoder().decode([String: Toto].self, from: data)["toto"]
    }
}

struct Object: Decodable {
    let id: String,
        customJson: CustomJson
}

#5

Ну если бы парсилась, я бы не подняль вопрос)
Если вы не против, я вам сейчас в ЛС эндпоинт вышлю


#6

Только что проверил вариант от @haymob’a, у меня парсится.
Для теста создал API для проверки https://run.mocky.io/v3/82778667-da2e-4bd0-9055-32d4a509f7c3
Модели я сделал почти идентичные, за исключением базовой, там я оставил тип String. Не пугайтесь ObjectMapper’a, это лишь обертка.

struct Object: Mappable {
    var customJson: String = ""
    
    init?(map: Map) {}
    mutating func mapping(map: Map) {
        customJson <- map["customJson"]
    }
}

struct CustomJson: Mappable {
    var toto: Toto?
    
    init?(map: Map) {}
    mutating func mapping(map: Map) {
        toto <- map["toto"]
    }
}

struct Toto: Mappable {
    var type,
        value,
        id: String!
    
    init?(map: Map) {}
    mutating func mapping(map: Map) {
        type <- map["type"]
        value <- map["value"]
        id <- map["id"]
    }
}

И в моем случае, когда я получаю ответ сервера, базовая модель Object хранит в себе строку, после чего эту строку нужно еще раз декодировать в CustomJson, который будет хранить соответственно уже нужные поля из Toto.

Получается так

let `object` = Object(JSONString: jsonData)
let customJson = CustomJson(JSONString: `object`.customJson)

#7

Шикарный сервис, спасибо)


#8

Если что, в Postman тоже можно сделать Mock Server
https://learning.postman.com/docs/designing-and-developing-your-api/mocking-data/setting-up-mock/