Flutter:如何正确地对“列表”进行 JSON 编码?

Posted

技术标签:

【中文标题】Flutter:如何正确地对“列表”进行 JSON 编码?【英文标题】:Flutter: How to JSON encode a `List` properly? 【发布时间】:2020-06-30 14:09:29 【问题描述】:

我正在尝试使用 Flutter 通过 REST API 将 List 传递给我的服务器。

下面是代码

 Future<void> saveOrderItemList(List<OrderItem> orderItems) async 
    int responsetag = 0;
    try 
      await http.post("http://url to post the data",
          body: convert.json.encode(orderItems.toJson()), //This line do not work
          headers: 
            "Accept": "application/json",
            "content-type": "application/json"
          ).then((http.Response response) 
        final int statusCode = response.statusCode;

        print("RESPONSE: " + response.body);
        print("STATUS CODE: " + statusCode.toString());

        if (statusCode < 200 || statusCode > 400 || response.body == null) 
          throw new Exception("Error while fetching data");
         else 
          responsetag = int.parse(response.body);
        
      );

      return responsetag;
     catch (error) 
      throw (error);
    
  

上面的代码无法运行,因为我无法使用convert.json.encode(orderItems.toJson())List 进行编码。

下面是我的OrderItem bean 及其序列化类的代码。

part 'order_item.g.dart';

/// An annotation for the code generator to know that this class needs the
/// JSON serialization logic to be generated.
@JsonSerializable()
class OrderItem 
  int idorderItem;
  FreshProducts freshProducts;
  Order order;
  ProductSize productSize;
  double orderItemExpectedPricePerKg;
  double orderItemQuantity;
  int dateCreated;
  int lastUpdated;

  OrderItem(
      
        this.idorderItem,
        this.freshProducts,
        this.order,
        this.productSize,
        this.orderItemExpectedPricePerKg,
        this.orderItemQuantity,
        this.dateCreated,
        this.lastUpdated

      );

  /// A necessary factory constructor for creating a new User instance
  /// from a map. Pass the map to the generated `_$OrderItemFromJson()` constructor.
  /// The constructor is named after the source class, in this case User.
  factory OrderItem.fromJson(Map<String, dynamic> json) => _$OrderItemFromJson(json);

  /// `toJson` is the convention for a class to declare support for serialization
  /// to JSON. The implementation simply calls the private, generated
  /// helper method `_$OrderItemToJson`.
  Map<String, dynamic> toJson() => _$OrderItemToJson(this);

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'order_item.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

OrderItem _$OrderItemFromJson(Map<String, dynamic> json) 
  return OrderItem(
    idorderItem: json['idorderItem'] as int,
    freshProducts: json['freshProducts'] == null
        ? null
        : FreshProducts.fromJson(json['freshProducts'] as Map<String, dynamic>),
    order: json['order'] == null
        ? null
        : Order.fromJson(json['order'] as Map<String, dynamic>),
        productSize: json['productSize'] == null
        ? null
        : ProductSize.fromJson(json['productSize'] as Map<String, dynamic>),
    orderItemExpectedPricePerKg:
        (json['orderItemExpectedPricePerKg'] as num)?.toDouble(),
    orderItemQuantity: (json['orderItemQuantity'] as num)?.toDouble(),
    dateCreated: json['dateCreated'] as int,
    lastUpdated: json['lastUpdated'] as int,
  );


Map<String, dynamic> _$OrderItemToJson(OrderItem instance) => <String, dynamic>
      'idorderItem': instance.idorderItem,
      'freshProducts': instance.freshProducts,
      'order': instance.order,
      'productSize': instance.productSize,
      'orderItemExpectedPricePerKg': instance.orderItemExpectedPricePerKg,
      'orderItemQuantity': instance.orderItemQuantity,
      'dateCreated': instance.dateCreated,
      'lastUpdated': instance.lastUpdated,
    ;

如何确保我可以将列表从颤振 http 传递给 POST

【问题讨论】:

【参考方案1】:

我解决了类似的问题。但是我的 List 是用其他键包裹的,例如 "data":listOfItemJson 。所以我首先创建了一个Map,就像var map = "data": MainOrderController.orderModel.toJson();,当我发布这个url时,我更新了发布机制,比如:

 var response =
          await http.post(url, headers: headers, body: jsonEncode(map));

注意:jsonEncode()import 'dart:convert'; 包的一部分。

我希望你能得到一个想法

【讨论】:

在您的问题中,您提到您正在使用convert.json.encode(orderItems.toJson()),但我想告诉您,我曾经将项目列表首先转换为地图。而且这个map也是json的字符串格式。我将列表转换为地图,因为我的帖子参数需要包装 json。然后我使用 jsonEncode() 方法对地图进行结束编码。 因此您可以尝试使用 jsonEndcode() 对列表进行编码 使用我的代码,你能给我一个例子吗?【参考方案2】:

我对此的看法是用https://github.com/k-paxian/dart-json-mapper 替换json_serializable

这很相似,但不要用样板文件过度膨胀你的代码,也不要强迫你维护大量的 '*.g.part' 文件等。

它不仅可以帮助您解决这种情况,还可以帮助您解决所有 Dart Object => JSON => Dart Object 的情况。

请先仔细阅读库自述文件,尤其是“基本设置”部分。

使用dart-json-mapper,您的代码可能如下所示:

import 'main.reflectable.dart' show initializeReflectable;
import 'package:dart_json_mapper/dart_json_mapper.dart' show jsonSerializable, JsonMapper;

@jsonSerializable
@Json(enumValues: ProductSize.values)
enum ProductSize Big, Small

@jsonSerializable
class Order 
// ...


@jsonSerializable
class FreshProducts 
// ...


@jsonSerializable
class OrderItem 
  int idorderItem;
  FreshProducts freshProducts;
  Order order;
  ProductSize productSize;
  double orderItemExpectedPricePerKg;
  double orderItemQuantity;
  int dateCreated;
  int lastUpdated;

  OrderItem(
      
        this.idorderItem,
        this.freshProducts,
        this.order,
        this.productSize,
        this.orderItemExpectedPricePerKg,
        this.orderItemQuantity,
        this.dateCreated,
        this.lastUpdated

      );


void main 
  initializeReflectable();

  final orderItems = <OrderItem>[OrderItem(), OrderItem(), OrderItem()];

  // Instead of convert.json.encode(orderItems.toJson())
  final orderItemsJson = JsonMapper.serialize(orderItems);

  // orderItemsJson will have Json string which you could pass as body to your post request


【讨论】:

【参考方案3】:

根据json_serializable和https://github.com/google/json_serializable.dart/issues/651,可以将以下内容放到根目录下的build.yaml中。 explicit_to_json 默认为 false,设置为 true 会显式调用嵌套的 toJson。

targets:
  $default:
    builders:
      json_serializable:
        options:
          # Options configure how source code is generated for every
          # `@JsonSerializable`-annotated class in the package.
          #
          # The default value for each is listed.
          explicit_to_json: true

【讨论】:

以上是关于Flutter:如何正确地对“列表”进行 JSON 编码?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter反序列化列表的列表

Flutter DistanceMatrix JSON 无法正确解析

在 Flutter 中使用 ListView 从 API 检索 json 对象列表时。拥有有状态或无状态小部件是不是正确?

如何从列表中映射 Flutter JSON 字符串?

在 Flutter 中提取 JSON 数据时遇到问题

如何有效地对抽象列表进行嵌套迭代?