假设我有 Customer
数据类型,其中包含 metadata
属性,该属性可以包含客户对象中的任何JSON字典
struct Customer {
let id: String
let email: String
let metadata: [String: Any]
}
{
"object": "customer",
"id": "4yq6txdpfadhbaqnwp3",
"email": "john.doe@example.com",
"metadata": {
"link_id": "linked-id",
"buy_count": 4
}
}
The metadata property can be any arbitrary JSON map object.
在我从 NSJSONDeserialization
中使用反序列化的JSON转换属性之前,但是使用新的Swift 4 Decodable
协议,我仍然无法想到这样做的方法 .
有人知道如何使用可解码协议在Swift 4中实现这一目标吗?
10 回答
我从this gist获得了一些灵感,我为
UnkeyedDecodingContainer
和KeyedDecodingContainer
写了一些扩展 . 你可以找到我的要点here的链接 . 通过使用此代码,您现在可以使用熟悉的语法解码任何Array<Any>
或Dictionary<String, Any>
:要么
Edit: 我发现有一个警告是解码字典数组
[[String: Any]]
所需的语法如下 . 您可能希望抛出错误而不是强制转换:EDIT 2: 如果您只是想将整个文件转换为字典,最好坚持使用JSONSerialization中的api,因为我还没有找到一种方法来扩展JSONDecoder本身以直接解码字典 .
扩展名
我也玩过这个问题,最后写了一个simple library for working with “generic JSON” types . (其中“generic”表示“没有事先知道结构” . )要点是用具体类型表示通用JSON:
然后,此类型可以实现
Codable
和Equatable
.当我找到旧的答案时,我只测试了一个简单的JSON对象案例,但不是一个空案例,这将导致运行时异常,如@slurmomatic和@zoul找到 . 对不起,这个问题 .
所以我通过一个简单的JSONValue协议尝试另一种方式,实现
AnyJSONValue
类型的擦除结构并使用该类型而不是Any
. 这是一个实现 .以下是解码时如何使用它
这个问题的问题是我们必须调用
value.jsonValue as? Int
. 我们需要等到Swift的土地,这将解决这个问题,或者至少帮助它变得更好 .[旧答案]
我在Apple Developer论坛上发布了这个问题,事实证明这很容易 .
我可以
在初始化程序中 .
首先想念那个是我的坏事 .
我的解决方案略有不同 .
让我们假设我们有一些不仅仅是简单的
[String: Any]
来解析Any可能是一个数组或一个嵌套字典或一个数组字典 .像这样的东西:
嗯,这是我的解决方案:
尝试使用它
您可以创建确认
Codable
协议的元数据结构,并使用Decodable
类创建如下所示的对象你可以看看BeyovaJSON
最简单和建议的方法是 create separate model for each dictionary or model that is in JSON .
这就是我的工作
Usage:
**我在解析时使用了可选的安全端,可以根据需要进行更改 .
Read more on this topic
这是更通用的(不仅
[String: Any]
,但[Any]
可以解码)和封装的方法(单独的实体用于此)受到@loudmouth答案的启发 .使用它看起来像:
JsonContainer
是一个帮助器实体,我们用它来解码JSON数据到JSON对象(数组或字典)而不扩展*DecodingContainer
(所以它不会干扰J11对象不是[String: Any]
所指的罕见情况) .请注意,数字和布尔类型由
NSNumber
支持,否则这样的东西将不起作用:你想要什么违背
Codable
的设计 .Codable
背后的想法是提供一种以类型安全的方式存档和取消归档数据的机制 . 这意味着您必须事先定义属性及其数据类型 . 我可以想到你的问题的两个解决方案:1.列出所有潜在的元数据键
通常,如果您深入到API的文档中,您将找到所有潜在元数据键的完整列表 . 定义
Metadata
结构,将这些键作为可选属性:我可以看到Swift设计师更喜欢这种方法 .
2.结合可解码和JSONSerialization
JSONSerialization
在类型安全的权衡中提供了巨大的动力 . 你绝对可以将它与Decodable
混淆,后者的设计理念就是相反:如果使用SwiftyJSON来解析JSON,则可以更新为4.1.0,它具有
Codable
协议支持 . 只要声明metadata: JSON
就可以了 .