Хорошо, задаю вопрос, похожий на этот , который я опубликовал на днях. Разница здесь в том, что мне интересно, может ли json подобъекта считываться как экранированная строка самого JSON, а не быть декодированным.
Учитывайте это json ...
{
"value" : "SomeValue",
"child" : {
"prop1" : "Value1",
"prop2" : "Value2"
}
}
Вы можете без проблем декодировать это в эти классы ...
class Wrapper : Codable {
let value : String
let child : ChildObject
}
class ChildObject : Codable {
let prop1 : String
let prop2 : String
}
Что мне интересно, так это возможность написать собственный декодер, который позволит мне декодировать его в этот класс. ...
class Wrapper : Codable {
let value : String
let child : String <-- Note: String
}
... и Wrapper.child равен этому ...
// Wrapper.child holds a string containing the escaped, raw JSON
Wrapper.child == "{\"prop1\":\"Value1\",\"prop2\":\"Value2\"}"
Единственное решение, которое я нашел до сих пор, - это явное декодирование во что-то вроде AnyCodable
(на GitHub здесь ), которая является прославленной реализацией с анонимной кодировкой, затем повторно сериализовайте ее обратно в JSON, прежде чем назначить ее фактическому свойству в инициализаторе. Кажется, немного излишним, но это работает.
public init(from decoder: Decoder) throws {
// Get the container for the CodingKeys
let container = try decoder.container(keyedBy: CodingKeys.self)
// Set 'value' directly as a string
value = try container.decode(String.self, forKey: .value)
// For 'child', Decode to an anonymous codable type,
// Re-serialize that codable type back to JSON data
// Convert that JSON data into a string, using that to set 'child'
// decode an type-erased Codable object
let anyCodable = try container.decode(AnyCodable.self, forKey: .child)
// Reencode it back to JSON
let encoder = JSONEncoder()
let childJsonData = try encoder.encode(anyCodable)
// Set that JSON on the object's string property
child = String(data:childJsonData, encoding:.utf8)!
}
Мне просто воняет, когда я декодирую, просто снова перекодирую. Надеюсь, что есть способ сделать это без этого дополнительного шага.