您可以将子 JSON 对象解码为其字符串表示形式而不是具体类型吗?
Posted
技术标签:
【中文标题】您可以将子 JSON 对象解码为其字符串表示形式而不是具体类型吗?【英文标题】:Can you decode a child JSON object into its string representation instead of a concrete type? 【发布时间】:2020-01-23 04:49:05 【问题描述】:好的,问一个类似于我前几天发布的this one 的问题。这里的区别是我想知道子对象的 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 上 here)之类的东西,这是一个美化的匿名编码实现,然后将其重新序列化回 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)!
解码对我来说只是感觉很“臭”,只是再次重新编码。希望有一种方法可以在没有额外步骤的情况下做到这一点。
【问题讨论】:
解决方案 smells 与您的要求一样非常规 ????。你必须重新编码这些东西。Codable
没有其他办法
我同意@vadian
问题出在解码的地方,无法知道具体的类型是什么。出于所有意图和目的,它只是一个将被交给其他地方的桶。我最初正在与后端团队合作,看看他们是否可以在那里将其编码为字符串,但他们说这会破坏其他系统,所以我正在尝试寻找替代方案。
告诉后端团队发送一个密钥type
以及字典,以便能够识别具体类型。发送不可预测的 JSON 是非常糟糕的做法。
他们已经这样做了。问题是这些具体类型是在完全独立的模块中定义的,并且没有办法将它们传递给解码器。相信我,我知道这不是最优的,但可以把它想象成通过 HTTP 发送它。它不知道具体的类型。接收器可以。同样在这里。第一次解码的地方不是使用站点。这只是把它送到那里。那部分确实知道具体的类型,它将在那里被解码。把它想象成 UPS。他们不知道甚至不在乎盒子里有一件衬衫或一架无人机。他们只是把盒子拿到它要去的地方。
【参考方案1】:
您正在寻找一种替代解决方案,而下面这个是替代解决方案。
在 ChildObject 类型上实现 CustomStringConvertible。
class ChildObject : Codable, CustomStringConvertible
let prop1 : String
let prop2 : String
var description: String
return "\(prop1) --- \(prop2)"
然后调用一个描述 getter
child = childJsonData.description
【讨论】:
以上是关于您可以将子 JSON 对象解码为其字符串表示形式而不是具体类型吗?的主要内容,如果未能解决你的问题,请参考以下文章