Flutter动态键JSON解码问题:仅获首个键值对的排查
问题分析
- 仅获取第一个键值对的原因:
ProductLineEntity.fromJson中使用json.keys.first只读取了第一个产品线键,直接忽略了其他键值对。readJson方法将包含所有产品线的单个Map对象直接传入ProductLineEntity.fromJson,没有遍历Map中的所有产品线条目。
- 未设置ProductCodeEntity的productLineName:解析产品代码时,没有将所属产品线名称传递给对应的实体类字段。
修正后的代码
1. 核心修正:readJson方法
遍历JSON中的所有产品线条目,逐个生成ProductLineEntity,同时为每个ProductCodeEntity设置所属产品线名称:
Future<List<ProductLineEntity>> readJson() async { try { final String jsonData = await rootBundle.loadString('assets/part_numbers2.json'); // 解析JSON,取出包含所有产品线的Map final Map<String, dynamic> productLinesMap = (json.decode(jsonData) as List<dynamic>).first; List<ProductLineEntity> productLines = []; // 遍历所有产品线键值对 productLinesMap.forEach((lineName, productCodesJson) { // 解析当前产品线的所有产品代码,并绑定产品线名称 List<ProductCodeEntity> codeList = (productCodesJson as List<dynamic>) .map((codeJson) => ProductCodeEntity.fromJson(codeJson)..productLineName = lineName) .toList(); productLines.add(ProductLineEntity( name: lineName, productCodeList: codeList, )); }); return productLines; } catch (error) { throw Exception('ProductLineEntity, Unexpected error reading JSON: $error'); } }
2. 可选优化:调整ProductCodeEntity的fromJson方法
如果想在解析时直接传入产品线名称,可修改fromJson增加参数,让逻辑更清晰:
class ProductCodeEntity { int? id; String? partNumber; bool? orderable; String? description; String? productLineName; ProductCodeEntity({ this.id, this.partNumber, this.orderable, this.description, this.productLineName, }); // 新增参数接收产品线名称 factory ProductCodeEntity.fromJson(Map<String, dynamic> json, {String? productLineName}) { return ProductCodeEntity( id: (json['id'] as num?)?.toInt(), partNumber: json['partNumber'] as String?, orderable: json['orderable'] as bool?, description: json['description'] as String?, productLineName: productLineName, ); } }
此时readJson中的代码解析部分需改为:
List<ProductCodeEntity> codeList = (productCodesJson as List<dynamic>) .map((codeJson) => ProductCodeEntity.fromJson(codeJson, productLineName: lineName)) .toList();
3. 简化ProductLineEntity.fromJson(可选)
由于readJson已直接处理实体创建,可删除原fromJson方法,或调整为更贴合场景的形式:
class ProductLineEntity { int? id; String? name; List<ProductCodeEntity>? productCodeList; ProductLineEntity({ this.id, this.name, this.productCodeList, }); // 可选:直接通过产品线名称和代码列表创建实体 factory ProductLineEntity.fromLine(String lineName, List<dynamic> codesJson) { List<ProductCodeEntity> codeList = codesJson .map((codeJson) => ProductCodeEntity.fromJson(codeJson, productLineName: lineName)) .toList(); return ProductLineEntity(name: lineName, productCodeList: codeList); } }
验证效果
修正后,readJson会遍历所有产品线键值对,生成完整的ProductLineEntity列表,且每个ProductCodeEntity都会正确带上所属的产品线名称,彻底解决仅获取第一个键值对的问题。
内容的提问来源于stack exchange,提问作者Joe G
相关产品推荐
相关产品推荐

