首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Dart中用List类型反序列化泛型JSON

如何在Dart中用List类型反序列化泛型JSON
EN

Stack Overflow用户
提问于 2022-05-14 15:21:02
回答 3查看 192关注 0票数 0

我想反序列化一些包含文章信息列表的JSON数据

代码语言:javascript
复制
{
    "data": [
        {
            "id": 1,
            "title": "First article",
            "createdDate": "2022-03-20T11:46:00",
            "content": "Markdown content",
            "author": 1,
            "category": 1
        },
        {
            "id": 2,
            "title": "Second article",
            "createdDate": "2022-03-20T11:46:00",
            "content": "Markdown content",
            "author": 1,
            "category": 1
        }
    ]
}

无论请求是什么,顶层都将有一个名为data的键。

因此,我创建了一个名为Entry的泛型类。

代码语言:javascript
复制
import 'package:json_annotation/json_annotation.dart';

part 'Entry.g.dart';

@JsonSerializable(genericArgumentFactories: true)

class Entry<TData> {
  Entry(this.data);

  TData data;

  factory Entry.fromJson(Map<String, dynamic> json,TData Function(dynamic json) fromJsonTData) => _$EntryFromJson(json,fromJsonTData);
  Map<String, dynamic> toJson(Object? Function(TData value) toJsonTData) => _$EntryToJson(this,toJsonTData);
}

对于一篇文章,我创建了一个名为NovelData的类

代码语言:javascript
复制
import 'dart:convert';
import 'dart:core';
import 'package:json_annotation/json_annotation.dart';

import 'Entry.dart';

part 'NovelData.g.dart';

@JsonSerializable(genericArgumentFactories: true)
class NovelData {
  NovelData(this.id, this.title, this.createdDate, this.content, this.author, this.category);

  int id;
  String title;
  String createdDate;
  String content;
  int author;
  int category;

  factory NovelData.fromJson(Map<String, dynamic> json) =>
      _$NovelDataFromJson(json);

  Map<String, dynamic> toJson() => _$NovelDataToJson(this);
}

现在,如果我想使用像Entry<List<Novel>>>这样的类型来反序列化上面的JSON数据,我应该做什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-05-15 19:44:33

您可以通过数据的完整路径访问它们。

数据的完整路径:映射=>键data =>数组=>数组索引=>映射

{}.data.[].0.{}

只需要上一节课。

代码语言:javascript
复制
import 'package:fast_json/fast_json_selector.dart' as parser;

void main() async {
  final path = '{}.data.[].0.{}';
  final pathLevel = path.split('.').length;
  final items = <Novel>[];
  void select(parser.JsonSelectorEvent event) {
    if (event.levels.length == pathLevel) {
      if (event.levels.join('.') == path) {
        final item = Novel.fromJson(event.lastValue as Map);
        items.add(item);
        event.lastValue = null;
      }
    }
  }

  parser.parse(_json, select: select);
  print(items.join('\n'));
}

final _json = '''
{
    "data": [
        {
            "id": 1,
            "title": "First article",
            "createdDate": "2022-03-20T11:46:00",
            "content": "Markdown content",
            "author": 1,
            "category": 1
        },
        {
            "id": 2,
            "title": "Second article",
            "createdDate": "2022-03-20T11:46:00",
            "content": "Markdown content",
            "author": 1,
            "category": 1
        }
    ]
}''';

class Novel {
  final int id;
  final String title;

  Novel({required this.id, required this.title});

  @override
  String toString() {
    return title;
  }

  static Novel fromJson(Map json) {
    return Novel(
      id: json['id'] as int,
      title: json['title'] as String,
    );
  }
}

输出:

代码语言:javascript
复制
First article
Second article

您可以在将数据添加到列表之前获取数据。结果也没什么不同。只是另一条通往数据的路径。

代码语言:javascript
复制
void main() async {
  final path = '{}.data.[].0';
  final pathLevel = path.split('.').length;
  final items = <Novel>[];
  void select(parser.JsonSelectorEvent event) {
    if (event.levels.length == pathLevel) {
      if (event.levels.join('.') == path) {
        final item = Novel.fromJson(event.lastValue as Map);
        items.add(item);
        event.lastValue = null;
      }
    }
  }

  parser.parse(_json, select: select);
  print(items.join('\n'));
}

此事件遵循对象创建事件(在较低的事件级别上):

JsonHandlerEvent.endObject => JsonHandlerEvent.element

您可以在将数据添加到列表后获取数据。但不会有那么高的效率。

代码语言:javascript
复制
void main() async {
  final path = '{}.data.[]';
  final pathLevel = path.split('.').length;
  final items = <Novel>[];
  void select(parser.JsonSelectorEvent event) {
    if (event.levels.length == pathLevel) {
      if (event.levels.join('.') == path) {
        final list = event.lastValue as List;
        items.addAll(list.map((e) => Novel.fromJson(e as Map)));
        list.clear();
      }
    }
  }

  parser.parse(_json, select: select);
  print(items.join('\n'));
}

JsonHandlerEvent.endObject => JsonHandlerEvent.element => JsonHandlerEvent.endArray

甚至从属性data。效率很低,因为所有的数据都存储在内存中。

代码语言:javascript
复制
void main() async {
  final path = '{}.data';
  final pathLevel = path.split('.').length;
  final items = <Novel>[];
  void select(parser.JsonSelectorEvent event) {
    if (event.levels.length == pathLevel) {
      if (event.levels.join('.') == path) {
        final list = event.lastValue as List;
        items.addAll(list.map((e) => Novel.fromJson(e as Map)));
        event.lastValue = null;
      }
    }
  }

  parser.parse(_json, select: select);
  print(items.join('\n'));
}

JsonHandlerEvent.endObject => JsonHandlerEvent.element => JsonHandlerEvent.endArray => JsonHandlerEvent.endKey

我甚至不会写关于最后一层的文章。这种低效的方式是没有意义的。然而,在前一个版本中也是如此。

JsonHandlerEvent.endObject => JsonHandlerEvent.element => JsonHandlerEvent.endArray => JsonHandlerEvent.endKey => JsonHandlerEvent.endObject

票数 0
EN

Stack Overflow用户

发布于 2022-05-14 15:26:17

有一个网站,它从json自动生成所有所需的代码。下面是一个例子:

代码语言:javascript
复制
// To parse this JSON data, do
//
//     final entry = entryFromJson(jsonString);

import 'dart:convert';

Entry entryFromJson(String str) => Entry.fromJson(json.decode(str));

String entryToJson(Entry data) => json.encode(data.toJson());

class Entry {
    Entry({
        this.data,
    });

    List<Datum> data;

    factory Entry.fromJson(Map<String, dynamic> json) => Entry(
        data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "data": List<dynamic>.from(data.map((x) => x.toJson())),
    };
}

class Datum {
    Datum({
        this.id,
        this.title,
        this.createdDate,
        this.content,
        this.author,
        this.category,
    });

    int id;
    String title;
    DateTime createdDate;
    String content;
    int author;
    int category;

    factory Datum.fromJson(Map<String, dynamic> json) => Datum(
        id: json["id"],
        title: json["title"],
        createdDate: DateTime.parse(json["createdDate"]),
        content: json["content"],
        author: json["author"],
        category: json["category"],
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "title": title,
        "createdDate": createdDate.toIso8601String(),
        "content": content,
        "author": author,
        "category": category,
    };
}
票数 0
EN

Stack Overflow用户

发布于 2022-05-16 04:47:23

您可以尝试我的jsonize包,它将处理任何TData类,无论它们在Entry数据列表中的哪个位置。

代码语言:javascript
复制
import 'package:jsonize/jsonize.dart';

abstract class TData {}

class Entry implements Jsonizable {
  Entry({
    required this.data,
  });
  factory Entry.empty() => Entry(data: []);

  List<TData> data;

  @override
  String get jsonClassCode => "Entry";

  @override
  Entry fromJson(json) => Entry(data: List<TData>.from(json["data"]));

  @override
  Map<String, dynamic> toJson() => {"data": data};
}

class NovelData extends TData implements Jsonizable {
  NovelData({
    required this.id,
    required this.title,
    required this.createdDate,
    required this.content,
    required this.author,
    required this.category,
  });
  factory NovelData.empty() => NovelData(
      id: 0,
      title: "",
      createdDate: DateTime(0),
      content: "",
      author: 0,
      category: 0);

  int id;
  String title;
  DateTime createdDate;
  String content;
  int author;
  int category;

  @override
  String get jsonClassCode => "NovelData";

  @override
  NovelData fromJson(json) => NovelData(
        id: json["id"],
        title: json["title"],
        createdDate: json["createdDate"],
        content: json["content"],
        author: json["author"],
        category: json["category"],
      );

  @override
  Map<String, dynamic> toJson() => {
        "id": id,
        "title": title,
        "createdDate": createdDate,
        "content": content,
        "author": author,
        "category": category,
      };
}

main() {
  Jsonize.registerClass(Entry.empty());
  Jsonize.registerClass(NovelData.empty());

  NovelData novel1 = NovelData(
      id: 1,
      title: "First article",
      createdDate: DateTime.now(),
      content: "Markdown content",
      author: 1,
      category: 1);
  NovelData novel2 = NovelData(
      id: 2,
      title: "Second article",
      createdDate: DateTime.now(),
      content: "Markdown content",
      author: 1,
      category: 1);
  Entry myEntry = Entry(data: [novel1, novel2]);

  String myEntryJson = Jsonize.toJson(myEntry);
  print(myEntryJson);
  Entry entryBackToLife = Jsonize.fromJson(myEntryJson);
  print(entryBackToLife);
}

jsonize可以做得更像处理枚举。就你而言,好处是:

  1. DateTime序列化由jsonize处理,不需要转换它。
  2. 您可以从TData派生新类并将它们放入您的Entry中,jsonize将处理它们并自动将其转换回原始类。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72241580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档