【问题标题】:How to parse dynamic JSON keys in dart如何在 dart 中解析动态 JSON 键
【发布时间】: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();
  }
}

【问题讨论】:

    标签: json flutter dart serialization deserialization


    【解决方案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
      • 所以,你的模型应该包含所有可能的类型。
      • 显然没有,甚至有一些方法可以解析动态键
      • 你可以看这里修改一下。 stackoverflow.com/questions/57976532/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-18
      • 1970-01-01
      • 2014-12-22
      • 2023-03-13
      • 2011-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多