使用未知键序列化 JSON
Posted
技术标签:
【中文标题】使用未知键序列化 JSON【英文标题】:Serialization of JSON with unknown key 【发布时间】:2019-01-06 01:54:36 【问题描述】:我正在使用json_serializable pub package 来满足我所有的 RESTful API 需求,而且效果很好,但现在我正在尝试序列化来自 Wikipedia 的内容。
我的问题是响应结构,其中一个键是预先未知的,并且根据返回的页面 ID 是动态的,这是一个示例:
我只想获取页面的介绍部分,我的查询是: https://en.wikipedia.org/w/api.php?action=query&format=json&prop=extracts&redirects=1&exintro=1&explaintext=1&titles=Stack%20Overflow
响应将是:
"batchcomplete": "",
"query":
"pages":
"21721040":
"pageid": 21721040,
"ns": 0,
"title": "Stack Overflow",
"extract": "Stack Overflow is a privately held website, the flagship site of ......."
最终我只想获得内部extract
字符串,但“在路上”我在pages
下有页面ID。
当我不知道关键是什么时,我找不到如何获取对象,既不使用json_serializable package,也不明确编写 JSON 导入代码。有可能吗?
PS,我确实认为我找到了一种需要两次 API 调用的方法 - 如果我添加 indexpageids 标志并将其设置为 true,i will receive an additional dictionary entry called pageids
with the page id numbers as string,那么我可以在第二次 API 调用。
我仍然不知道我会做的确切方式,但我很确定这是可能的,但每次发送 2 个 API 请求很昂贵,我想知道是否有更优雅的方式来做.
【问题讨论】:
你不能使用Map<String, Page>
作为pages
的类型吗?
【参考方案1】:
确保您使用最新版本的 json_serializable。对键值对使用Map<String, Page>
:
@JsonSerializable()
class Query
final Map<String, Page> pages;
Query(this.pages);
factory Query.fromJson(Map<String, dynamic> json) => _$QueryFromJson(json);
Map<String, dynamic> toJson() => _$QueryToJson(this);
只是为了证明它有效,下面是 json_serializable 生成的内容:
Query _$QueryFromJson(Map<String, dynamic> json)
return new Query((json['pages'] as Map<String, dynamic>)?.map((k, e) =>
new MapEntry(
k, e == null ? null : new Page.fromJson(e as Map<String, dynamic>))));
【讨论】:
【参考方案2】:您可以获取 json 的键,然后使用该键获取值作为
var response = await http.get(API_ENDPOINT);
var responseJson = json.decode(response.body);
Map<String, dynamic> json =responseJson['query']['pages'];
String pageId = json.keys.toList()[0]; // 0 for first page, you can iterate for multiple pages
firstPage = json[pageId];
String title = firstPage["title"];
【讨论】:
【参考方案3】:如果动态键中还有另一层动态键,你会怎么做?我必须为我的第二个类编辑生成的 json_serializable 以仅使用 json 而不是生成的 json['key']。
Page _$PageFromJson(Map<String, dynamic> json)
return new Page((json as Map<String, dynamic>)?.map((k, e) =>
new MapEntry(
k, e == null ? null : new SecondPage.fromJson(e as Map<String, dynamic>))));
感觉有更好的办法?因为每次我对任何文件进行更改并运行生成器时,生成的代码都会被覆盖。
我是 SO 新手,所以我无法评价答案和编写 cmets。但是 boformer 的回答对我有所帮助,但后来我遇到了第二个问题。
编辑:我通过反复试验找到了解决方案,使用:
class Query
final Map<String, Map<String, SecondPage>> pages;
【讨论】:
如果您在这篇文章或其他任何地方都找不到您的问题的答案,这是一个提出自己问题的好机会。作为答案发布的问题往往不会被能够回答的人看到。 是的,我想过,但我不想只做一点修改就创建一个副本。不知道我是否可以参考一个问题。但我现在找到了答案并更新了我的回复。谢谢以上是关于使用未知键序列化 JSON的主要内容,如果未能解决你的问题,请参考以下文章
如何将多个键值条目的 JSON 对象反序列化为 Rust 中的自定义结构
jackson 序列化忽略未知字段: How to Ignore Unknown Properties While Parsing JSON in Java