You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dart/Flutter中解析API返回的含position嵌套对象的复杂JSON?

在Dart/Flutter中解析含动态键的嵌套复杂JSON数据

针对你遇到的position字段包含动态数字键(如"84"、"86")的嵌套JSON解析问题,下面是具体的实现方案:

核心思路

position里的键是不固定的字符串型数字,无法直接用固定类属性映射,因此我们用Map<String, PositionItem>来存储这些动态项,再为每个嵌套层级创建对应的实体类,逐层解析。

步骤1:创建实体类

根据JSON结构,从最底层的嵌套对象开始定义类,每个类实现fromJson工厂方法来完成解析:

class Product {
  final int id;
  final String name;
  final String slug;

  Product({required this.id, required this.name, required this.slug});

  factory Product.fromJson(Map<String, dynamic> json) {
    return Product(
      id: json['id'] as int,
      name: json['name'] as String,
      slug: json['slug'] as String,
    );
  }
}

class MainPrice {
  final int id;
  final int itemId;
  final String itemType;
  final String price;
  final String oldPrice;
  final DateTime? createdAt;
  final DateTime? updatedAt;

  MainPrice({
    required this.id,
    required this.itemId,
    required this.itemType,
    required this.price,
    required this.oldPrice,
    this.createdAt,
    this.updatedAt,
  });

  factory MainPrice.fromJson(Map<String, dynamic> json) {
    return MainPrice(
      id: json['id'] as int,
      itemId: json['item_id'] as int,
      itemType: json['item_type'] as String,
      price: json['price'] as String,
      oldPrice: json['old_price'] as String,
      createdAt: json['created_at'] != null ? DateTime.parse(json['created_at']) : null,
      updatedAt: json['updated_at'] != null ? DateTime.parse(json['updated_at']) : null,
    );
  }
}

class OfferProduct {
  final int id;
  final String priceValue;
  final Product product;
  final MainPrice mainPrice;

  OfferProduct({
    required this.id,
    required this.priceValue,
    required this.product,
    required this.mainPrice,
  });

  factory OfferProduct.fromJson(Map<String, dynamic> json) {
    return OfferProduct(
      id: json['id'] as int,
      priceValue: json['price_value'] as String,
      product: Product.fromJson(json['product'] as Map<String, dynamic>),
      mainPrice: MainPrice.fromJson(json['main_price'] as Map<String, dynamic>),
    );
  }
}

class PositionItem {
  final String price;
  final int priceValue;
  final int id;
  final int itemId;
  final OfferProduct product;
  final String itemType;
  final int quantity;
  final int maxQuantity;
  final int weight;
  final String property;

  PositionItem({
    required this.price,
    required this.priceValue,
    required this.id,
    required this.itemId,
    required this.product,
    required this.itemType,
    required this.quantity,
    required this.maxQuantity,
    required this.weight,
    required this.property,
  });

  factory PositionItem.fromJson(Map<String, dynamic> json) {
    return PositionItem(
      price: json['price'] as String,
      priceValue: json['price_value'] as int,
      id: json['id'] as int,
      itemId: json['item_id'] as int,
      product: OfferProduct.fromJson(json['product'] as Map<String, dynamic>),
      itemType: json['item_type'] as String,
      quantity: json['quantity'] as int,
      maxQuantity: json['max_quantity'] as int,
      weight: json['weight'] as int,
      property: json['property'] as String,
    );
  }
}

class PriceInfo {
  final String price;
  final int priceValue;

  PriceInfo({required this.price, required this.priceValue});

  factory PriceInfo.fromJson(Map<String, dynamic> json) {
    return PriceInfo(
      price: json['price'] as String,
      priceValue: json['price_value'] as int,
    );
  }
}

class Order {
  final int id;
  final Map<String, PositionItem> positions;
  final PriceInfo shippingPrice;
  final PriceInfo positionTotalPrice;
  final PriceInfo totalPrice;
  final int quantity;
  final int totalQuantity;
  final int weight;
  final int? paymentMethodId;
  final int? shippingTypeId;
  final dynamic userData;
  final dynamic shippingAddress;
  final dynamic billingAddress;
  final dynamic property;

  Order({
    required this.id,
    required this.positions,
    required this.shippingPrice,
    required this.positionTotalPrice,
    required this.totalPrice,
    required this.quantity,
    required this.totalQuantity,
    required this.weight,
    this.paymentMethodId,
    this.shippingTypeId,
    this.userData,
    this.shippingAddress,
    this.billingAddress,
    this.property,
  });

  factory Order.fromJson(Map<String, dynamic> json) {
    // 处理动态键的position字段
    final positionMap = json['position'] as Map<String, dynamic>;
    final positions = positionMap.map((key, value) => MapEntry(
          key,
          PositionItem.fromJson(value as Map<String, dynamic>),
        ));

    return Order(
      id: json['id'] as int,
      positions: positions,
      shippingPrice: PriceInfo.fromJson(json['shipping_price'] as Map<String, dynamic>),
      positionTotalPrice: PriceInfo.fromJson(json['position_total_price'] as Map<String, dynamic>),
      totalPrice: PriceInfo.fromJson(json['total_price'] as Map<String, dynamic>),
      quantity: json['quantity'] as int,
      totalQuantity: json['total_quantity'] as int,
      weight: json['weight'] as int,
      paymentMethodId: json['payment_method_id'] as int?,
      shippingTypeId: json['shipping_type_id'] as int?,
      userData: json['user_data'],
      shippingAddress: json['shipping_address'],
      billingAddress: json['billing_address'],
      property: json['property'],
    );
  }
}

步骤2:解析API返回的JSON

拿到API返回的JSON字符串后,用jsonDecode转成Map,再通过Order.fromJson生成实体对象:

import 'dart:convert';

// 假设apiResponse是从接口获取的JSON字符串
final apiResponse = '''你的API返回的JSON内容''';
final jsonMap = jsonDecode(apiResponse) as Map<String, dynamic>;
final order = Order.fromJson(jsonMap);

// 访问动态键对应的项
final item84 = order.positions['84'];
final item86 = order.positions['86'];

// 示例:打印商品名称
if (item84 != null) {
  print(item84.product.product.name);
}

可选:用json_serializable自动生成解析代码

如果项目中使用json_serializable库,可以简化解析代码的编写:

  1. 添加依赖到pubspec.yaml:
dependencies:
  json_annotation: ^4.8.1

dev_dependencies:
  build_runner: ^2.4.4
  json_serializable: ^6.7.0
  1. 给每个实体类添加@JsonSerializable()注解,并生成对应的fromJson/toJson方法:
import 'package:json_annotation/json_annotation.dart';

part 'order.g.dart';

@JsonSerializable()
class Product {
  final int id;
  final String name;
  final String slug;

  Product({required this.id, required this.name, required this.slug});

  factory Product.fromJson(Map<String, dynamic> json) => _$ProductFromJson(json);
  Map<String, dynamic> toJson() => _$ProductToJson(this);
}

// 其他类同理添加@JsonSerializable()注解...

@JsonSerializable()
class Order {
  final int id;
  @JsonKey(name: 'position')
  final Map<String, PositionItem> positions;
  final PriceInfo shippingPrice;
  // 其他字段...

  Order({required this.id, required this.positions, required this.shippingPrice, ...});

  factory Order.fromJson(Map<String, dynamic> json) => _$OrderFromJson(json);
  Map<String, dynamic> toJson() => _$OrderToJson(this);
}
  1. 运行命令生成解析代码:
flutter pub run build_runner build

注意事项

  • 动态键是字符串类型(如"84"),所以Map的键类型用String而非int;
  • 处理JSON中的可选字段(如created_at可能为null),用可空类型接收;
  • 带空格的价格字符串(如"1 000.00")直接用String类型接收,后续可按需格式化处理。

内容的提问来源于stack exchange,提问作者Meylis Annagurbanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:57:05