json - 解码具有相同信封但内容不同的 JSON 响应
问题描述
我正在访问一个 web api,作为响应,它发送包装在同一个信封中的不同有效负载,如下所示:
获取食谱列表:
{
"status": "SUCCESS",
"messages": [],
"input": null,
"output": [
{
"id": 1,
"title": "Egg with bacon"
},
{
"id": 2,
"title": "Ice cream"
}
]
}
获取一个食谱:
{
"status": "SUCCESS",
"messages": [],
"input": {"id": 1},
"output": {
"id": 1,
"title": "Egg with bacon"
}
}
错误响应:
{
"status": "ERROR",
"messages": ["Recipe not found"],
"input": {"id": 4},
"output": null
}
类别列表:
{
"status": "SUCCESS",
"messages": [],
"input": null,
"output": [
{
"id": 1,
"title": "Deserts"
},
{
"id": 2,
"title": "Main Courses"
}
]
}
因此,信封键始终存在。输入是键值对象或空值,消息总是字符串数组或空数组,状态是字符串。但输出可能不同。它可以是一种Recipe 结构、Recipe 结构数组或Category 结构。
我的问题是:我如何解码这个 json 而无需每次都为信封编写相同的解码逻辑?我只想为包络编写一次解码器,并为输出注入不同的解码器。
解决方案
您可以创建一个可解码的结构,用于将输入和输出包装到其中。
这看起来像:
struct ResponseContainer<Input: Decodable, Output: Decodable>: Decodable {
var status: String
var messages: [String]
var input: Input?
var output: Output
}
使用这个,如果你想解码一个单一的配方,你只需将你的Recipe
结构包装到响应容器中:
// used to decode the `input`
struct InputId: Decodable {
var id: Int
}
// content of the `output`
struct Recipe: Decodable {
var id: Int
var title: String
}
try? JSONDecoder().decode(ResponseContainer<InputId, Recipe>.self, from: singleRecipeJson)
如果要解码食谱列表,只需对另一个结构或数组进行相同的处理:
// As the input is expected to be null, you can use a dummy struct in the wrapper.
struct Empty: Decodable {}
try! JSONDecoder().decode(ResponseContainer<Empty, [Recipe]>.self, from: multipleRecipeJson)
注意: dummy structEmpty
可能没有用,因为它增加了很多复杂性,并且用于解析input
有效负载的属性,这看起来像您发送给 API 的东西(所以基本上您已经知道它,可以忽略它)。在这种情况下,包装器看起来像这样:
struct ResponseContainer<Output: Decodable>: Decodable {
var status: String
var messages: [String]
var output: Output
}
推荐阅读
- javascript - 如何在 ng-repeat 中按回车键调用函数
- javascript - 使用唯一 ID 从状态数组中删除对象
- javascript - 在 HTML 网页中,noscript 标签内的内容不会被具有脚本阻止扩展的浏览器呈现
- f# - F#如何保存惰性/复制非强制惰性语句
- php - 如何处理 laravel snappyPDF 中的错误异常?
- php - 我遇到了 PHP 和附加文件的问题
- neo4j - 如何在 Cypher 中使用一条语句创建所有边?
- python - 散景服务--show myapp
- python - 使用 CPLEX Python API 编写自定义变量选择方法
- javascript - 将 JSON 作为道具传递 - 无法读取未定义的属性“名称”