如何在Dart中解析动态JSON键

3

我有一个API,返回带有动态键的JSON,即每个GET请求的键值都会更改。

例如:这是JSON的格式。

我在Dart中有一个书籍模型,

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();
  }
}
2个回答

3
如果您不知道键名,但知道这是一个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 Map,您可以通过.keys访问键(然后无需提前了解它们即可遍历它们),并且可以通过.values访问值(并完全忽略键)。每个值都是一本书的列表,您可以使用现有的静态函数解析它们。要包含流派,您必须说明要记住流派的方式。最简单的方法是将数据保留为Map:
var categoriedBooks = {for (var genre in json) 
    genre: Book.listFromJson(json[genre])
};

这将创建一个具有相同键(流派)的映射,但值现在是Book列表。


0

您的响应模型包含两个不同的数组,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,
    };
}

您可以使用网站将您的JSON转换为任何Dart模型。


1
嘿,问题在于“惊悚片”和“为您推荐”的内容不是固定的。有时会变成“恐怖片”和“浪漫片”。 - Nithin Sai
所以,您的模型应包含所有可能的类型。 - Akif
显然并非如此,甚至可以解析动态键的某种方法。 - Nithin Sai
你可以在这里查看并修改它。https://stackoverflow.com/questions/57976532/flutter-dart-deserialize-a-json-with-dynamic-key-but-structured-values-into-map - Akif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接