I'm trying to decode the following JSON in Flutter and I am only getting the first key/value pair in my response. The first level keys (i.e. "Product Line 1", etc.) will all be dynamic and I need to capture those keys as values to add as a variable in my ProductCodeEntity
class. Can someone point out what I'm doing wrong?
[
{
"Product line 1": [
{"partNumber": "160-9013-900", "orderable": true, "description": "Part Number 1 Description"},
{"partNumber": "160-9104-900", "orderable": true, "description": "Part Number 2 Description"},
{"partNumber": "160-9105-900", "orderable": false, "description": "Part Number 3 Description"}
],
"Product line 2": [
{"partNumber": "160-9113-900", "orderable": true, "description": "Part Number 4 Description"},
{"partNumber": "160-9114-900", "orderable": true, "description": "Part Number 5 Description"},
{"partNumber": "160-9115-900", "orderable": false, "description": "Part Number 6 Description"}
],
"Product line 3": [
{"partNumber": "160-9205-900", "orderable": true, "description": "Part Number 7 Description"},
{"partNumber": "160-9211-900", "orderable": true, "description": "Part Number 8 Description"},
{"partNumber": "160-9212-900", "orderable": false, "description": "Part Number 9 Description"}
]
}
]
My ProductLineEntity
class looks like this. I believe the problem is in the
factory ProductLineEntity.fromJson()
function, but I haven't been able to get it to work.
class ProductLineEntity {
int? id;
String? name;
List<ProductCodeEntity>? productCodeList;
ProductLineEntity({
this.id,
this.name,
this.productCodeList,
});
factory ProductLineEntity.fromJson(Map<String, dynamic> json) {
final List<ProductCodeEntity> productCodes = (json[json.keys.first] as List)
.map((productCodeJson) => ProductCodeEntity.fromJson(productCodeJson))
.toList();
return ProductLineEntity(
name: json.keys.first,
productCodeList: productCodes,
);
}
}
My ProductCodeEntity
class looks like this:
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) {
return ProductCodeEntity(
id: (json['id'] as num?)?.toInt(),
partNumber: json['partNumber'] as String?,
orderable: json['orderable'] as bool?,
description: json['description'] as String?,
productLineName: json['productLineName'] as String?,
);
}
}
Here is my code to read the JSON file:
Future<List<ProductLineEntity>> readJson() async {
List<ProductLineEntity> productLineFromJson(dynamic str) =>
List<ProductLineEntity>.from(
(str as List<dynamic>).map((x) => ProductLineEntity.fromJson(x)));
try {
final String jsonData =
await rootBundle.loadString('assets/part_numbers2.json');
final response = (json.decode(jsonData) as List<dynamic>);
List<ProductLineEntity> productLines = productLineFromJson(response);
return productLines;
} catch (error) {
throw Exception(
'ProductLineEntity, Unexpected error reading JSON: $error');
}
}
Here is the revised code
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logger/logger.dart';
void main() {
runApp(const MaterialApp(home: TestPage()));
}
class TestPage extends StatefulWidget {
const TestPage({super.key});
@override
State<TestPage> createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
var logger = Logger(
printer: PrettyPrinter(),
);
@override
void initState() {
super.initState();
logger.init;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: TextButton(
onPressed: () async {
List<ProductLineEntity> productLines = await readJson1();
logger.i(json.encode(productLines));
},
child: Text('Read JSON'),
),
);
}
Future<List<ProductLineEntity>> readJson1() async {
List<ProductLineEntity> products = [];
try {
final String jsonData =
await rootBundle.loadString('assets/part_numbers2.json');
final List<dynamic> response = json.decode(jsonData);
for (var productLine in response) {
productLine.forEach((key, value) {
products.add(ProductLineEntity.fromJson(key, value));
});
}
logger.i(products);
return products;
} catch (error) {
throw Exception(
'ProductLineEntity, Unexpected error reading JSON: $error');
}
}
}
class ProductLineEntity {
int? id;
String? name;
List<ProductCodeEntity>? productCodeList;
ProductLineEntity({
this.id,
this.name,
this.productCodeList,
});
factory ProductLineEntity.fromJson(String key, List<dynamic> value) {
return ProductLineEntity(
name: key,
productCodeList: value.map((e) => ProductCodeEntity.fromJson(e)).toList(),
);
}
Map toJson() {
Map<String, dynamic> data = {};
data['name'] = name;
data['productCodeList'] =
productCodeList?.map((e) => e.toJson()).toList() ?? [];
data['id'] = id;
return data;
}
}
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) {
return ProductCodeEntity(
id: (json['id'] as num?)?.toInt(),
partNumber: json['partNumber'] as String?,
orderable: json['orderable'] as bool?,
description: json['description'] as String?,
productLineName: json['productLineName'] as String?,
);
}
Map toJson() => {
'id': id,
'partNumber': partNumber,
'orderable': orderable,
'description': description,
'productLineName': productLineName
};
}