【问题标题】:Serialization of JSON with unknown key使用未知键序列化 JSON
【发布时间】: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 的类型吗?

标签: json rest api dart flutter


【解决方案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;
      

      【讨论】:

      • 如果您在这篇文章或其他任何地方都找不到您的问题的答案,这是一个提出自己问题的好机会。作为答案发布的问题往往不会被能够回答的人看到。
      • 是的,我想过,但我不想只做一点修改就创建一个副本。不知道我是否可以参考一个问题。但我现在找到了答案并更新了我的回复。谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      相关资源
      最近更新 更多