如何在 dart 中解析动态 JSON 键

Posted

技术标签:

【中文标题】如何在 dart 中解析动态 JSON 键【英文标题】:How to parse dynamic JSON keys in dart 【发布时间】:2021-11-12 00:31:56 【问题描述】:

我有一个 API 可以返回带有动态键的 JSON,即每次 GET 请求时键值都会发生变化。

例如:这是 JSON 的格式。

我有一个飞镖模型,

class Book 
  String id = "";
  String title = "";
  
  Book();
  
  Book.fromJson(Map<String, dynamic> json) 
    id = json['id'];
    title = json['title'];
  
  
  static List<Book> listFromJson(List<dynamic> json) 
    return json.map((val) => Book.fromJson(val)).toList();
  

和 JSON 响应,


    "Recommended For You" : [
        
            "id" : "001",
            "title" : "title001"
        ,
        ...
    ],
    "Thrillers" : [
        
            "id" : "005",
            "title" : "title005"
        ,
        ...
    ]

鉴于类型(如Thrillers)可以改变(即它是动态的并且可能因每个用户而改变),如何根据类型将其解析为书籍列表?

编辑 1

ThrillersRecommended For You 不是恒定的,有时可能会更改为 HorrorRomantic 或其他内容。它是动态的

编辑 2:解决方案

感谢@lrn 的解决方案,我想出了一个新的类

class Recommendations 
  String recommendationType;
  List<Book> recommendations;

  @override
  String toString() 
    return 'Recomendations[title: $recommendationType]';
  

  Recommendations.fromJson(MapEntry<String, dynamic> json) 
    if (json == null) return;
    this.recommendationType = json.key;
    this.recommendations = Book.listFromJson(json.value);
  

  static List<Recommendations> listFromJson(Map<String, dynamic> json) 
    return json == null
        ? List<Recommendations>.empty()
        : json.entries
            .map((value) => new Recommendations.fromJson(value))
            .toList();
  

【问题讨论】:

【参考方案1】:

如果您不知道键,但知道它是一个 JSON 映射,其中值是您要查找的图书列表,我会写:

List<Book> parseCategorizedBooksJson(Map<String, dynamic> json) =>
  [for (var books in json.values) ...Book.listFromJson(books)];

List<Book> parseCategorizedBooksJson(Map<String, dynamic> json) =>
  [for (var books in json.values) 
     for (var book in books) Book.fromJson(book)];

(避免建立中间书籍列表)。

有了这个,您只需迭代外部映射的 ,并忽略键。 JSON 映射只是普通的 Dart Maps,您可以以 .keys 访问键(然后无需提前知道它们就可以通过它们)并以 .values 访问值(并完全忽略键) .

每个值都是书籍列表,您可以使用现有的静态函数对其进行解析。

要包含流派,您必须说明您希望如何记住流派。最简单的是将数据保留为地图:

var categoriedBooks = for (var genre in json) 
    genre: Book.listFromJson(json[genre])
;

这会使用相同的键(流派)构建一个映射,但其中的值现在是 Books 的列表。

【讨论】:

【参考方案2】:

您的响应模型包含两个不同的数组,recommendedForYouthrillers。所以,你可以这样处理:

// To parse this JSON data, do
//
//     final responseModel = responseModelFromJson(jsonString);

import 'dart:convert';

ResponseModel responseModelFromJson(String str) => ResponseModel.fromJson(json.decode(str));

String responseModelToJson(ResponseModel data) => json.encode(data.toJson());

class ResponseModel 
    ResponseModel(
        this.recommendedForYou,
        this.thrillers,
    );

    List<Book> recommendedForYou;
    List<Book> thrillers;

    factory ResponseModel.fromJson(Map<String, dynamic> json) => ResponseModel(
        recommendedForYou: json["Recommended For You"] == null ? null : List<Book>.from(json["Recommended For You"].map((x) => Book.fromJson(x))),
        thrillers: json["Thrillers"] == null ? null : List<Book>.from(json["Thrillers"].map((x) => Book.fromJson(x))),
    );

    Map<String, dynamic> toJson() => 
        "Recommended For You": recommendedForYou == null ? null : List<dynamic>.from(recommendedForYou.map((x) => x.toJson())),
        "Thrillers": thrillers == null ? null : List<dynamic>.from(thrillers.map((x) => x.toJson())),
    ;


class Book 
    Book(
        this.id,
        this.title,
    );

    String id;
    String title;

    factory Book.fromJson(Map<String, dynamic> json) => Book(
        id: json["id"] == null ? null : json["id"],
        title: json["title"] == null ? null : json["title"],
    );

    Map<String, dynamic> toJson() => 
        "id": id == null ? null : id,
        "title": title == null ? null : title,
    ;

您可以使用此site 将您的 json 转换为任何 dart 模型。

【讨论】:

嘿,问题是ThrillersRecommended For You 不是恒定的。有时它会更改为 HorrorRomantic 所以,你的模型应该包含所有可能的类型。 显然没有,甚至有一些方法可以解析动态键 你可以看这里修改一下。 ***.com/questions/57976532/…

以上是关于如何在 dart 中解析动态 JSON 键的主要内容,如果未能解决你的问题,请参考以下文章

如何解析嵌套 JSON 结果中的动态 JSON 键?

如果将来添加任何键,json如何解析动态键和值

如何解析具有动态键名的嵌套 json

如何在 Flutter Dart 中迭代 JSON Map 并检索键值结果?

如何编写解析此 JSON 的 Dart 模型类?

在 Dart 中解析没有名称的 json 数组