Flutter如何用JSON数据渲染温度、液位、电池图表?解析报错求助
Flutter新手求助:JSON数据渲染图表时的Model数据读取错误
问题背景
我是Flutter新手,希望利用给定的JSON数据渲染温度(Temperature)、液氮液位(LiquidNitrogenLevel)和电池(Battery)的图表,但在通过Model类读取数据时出现错误。
原始JSON数据
{ "data": { "container_id": 123, "container_serial_no": "CM22TLB101", "readings": [ { "temperature": [ { "timestamp": "2023-03-10T12:00:00.562060", "value": 19.56 }, { "timestamp": "2023-03-10T12:00:02.573979", "value": 19.56 }, { "timestamp": "2023-03-10T12:00:02.744149", "value": 19.56 }, { "timestamp": "2023-03-10T12:00:04.653301", "value": 19.56 }, { "timestamp": "2023-03-10T12:00:06.633112", "value": 19.56 } ] }, { "liquidNitrogenLevel": [ { "timestamp": "2023-03-10T12:00:00.562060", "value": 72 }, { "timestamp": "2023-03-10T12:00:02.573979", "value": 72 }, { "timestamp": "2023-03-10T12:00:02.744149", "value": 73 }, { "timestamp": "2023-03-10T12:00:04.653301", "value": 73 }, { "timestamp": "2023-03-10T12:00:06.633112", "value": 70 } ] }, { "battery": [ { "timestamp": "2023-03-10T12:00:00.562060", "value": 4.8 }, { "timestamp": "2023-03-10T12:00:02.573979", "value": 4.8 }, { "timestamp": "2023-03-10T12:00:02.744149", "value": 4.8 }, { "timestamp": "2023-03-10T12:00:04.653301", "value": 4.8 } ] } ] }, "status": "success" }
定义的Model类
ChartModel类
class ChartModel { Data? data; String? status; ChartModel({this.data, this.status}); ChartModel.fromJson(Map<String, dynamic> json) { data = json['data'] != null ? new Data.fromJson(json['data']) : null; status = json['status']; } }
Data类
class Data { int? containerId; String? containerSerialNo; List<Readings>? readings; Data({this.containerId, this.containerSerialNo, this.readings}); Data.fromJson(Map<String, dynamic> json) { containerId = json['container_id']; containerSerialNo = json['container_serial_no']; if (json['readings'] != null) { readings = <Readings>[]; json['readings'].forEach((v) { readings!.add(new Readings.fromJson(v)); }); } } }
Readings类
class Readings { List<Temperature>? temperature; List<LiquidNitrogenLevel>? liquidNitrogenLevel; List<Battery>? battery; Readings({this.temperature, this.liquidNitrogenLevel, this.battery}); Readings.fromJson(Map<String, dynamic> json) { if (json['temperature'] != null) { temperature = <Temperature>[]; json['temperature'].forEach((v) { temperature!.add(new Temperature.fromJson(v)); }); } if (json['liquidNitrogenLevel'] != null) { liquidNitrogenLevel = <LiquidNitrogenLevel>[]; json['liquidNitrogenLevel'].forEach((v) { liquidNitrogenLevel!.add(new LiquidNitrogenLevel.fromJson(v)); }); } if (json['battery'] != null) { battery = <Battery>[]; json['battery'].forEach((v) { battery!.add(new Battery.fromJson(v)); }); } } }
Temperature类
class Temperature { String? timestamp; var value; Temperature({this.timestamp, this.value}); Temperature.fromJson(dynamic json) { timestamp = json['timestamp']; value = json['value']; } }
LiquidNitrogenLevel类
class LiquidNitrogenLevel { String? timestamp; var value; LiquidNitrogenLevel({this.timestamp, this.value}); LiquidNitrogenLevel.fromJson(Map<String, dynamic> json) { timestamp = json['timestamp']; value = json['value']; } }
Battery类
class Battery { String? timestamp; var value; Battery({this.timestamp, this.value}); Battery.fromJson(Map<String, dynamic> json) { timestamp = json['timestamp']; value = json['value']; } }
出错代码与错误信息
出错代码
final serviceData = context.read<ChartService>().model; var lst = serviceData!.data!.readings!; print('len: ${serviceData!.data!.readings![0].temperature!}'); for (int i = 0; i < lst!.length; i++) { (lst[i].temperature!) .map( (e) => Temperature.fromJson(e), ) .toList(); }
错误信息
Class 'Temperature' has no instance method '[]'. Receiver: Instance of 'Temperature' Tried calling: []("timestamp")
解决方案
错误原因
你已经通过Model的fromJson方法把原始JSON数据解析成了Temperature对象实例,但在遍历lst[i].temperature!时,再次调用Temperature.fromJson(e),此时的e已经是Temperature类型的实例,而不是Map<String, dynamic>类型,所以Temperature.fromJson方法内部尝试调用json['timestamp']时,会因为实例没有[]方法而报错。
修正后的代码
直接使用已经解析好的Temperature实例即可,不需要再次调用fromJson:
final serviceData = context.read<ChartService>().model; if (serviceData?.data?.readings != null) { // 获取温度数据 final temperatureList = serviceData!.data!.readings![0].temperature ?? []; // 遍历温度数据,可直接使用timestamp和value for (var temp in temperatureList) { print('时间: ${temp.timestamp}, 温度: ${temp.value}'); } // 获取液氮液位数据 final nitrogenLevelList = serviceData.data!.readings![1].liquidNitrogenLevel ?? []; for (var level in nitrogenLevelList) { print('时间: ${level.timestamp}, 液位: ${level.value}'); } // 获取电池数据 final batteryList = serviceData.data!.readings![2].battery ?? []; for (var battery in batteryList) { print('时间: ${battery.timestamp}, 电量: ${battery.value}'); } }
渲染图表的后续建议
可以使用Flutter常用图表库(如charts_flutter或syncfusion_flutter_charts),将上述数据转换成图表所需的格式。以charts_flutter为例,先定义一个图表数据类:
class ChartData { final DateTime time; final double value; ChartData(this.time, this.value); }
然后把Temperature数据转换成ChartData列表:
List<ChartData> tempChartData = temperatureList.map((temp) { return ChartData( DateTime.parse(temp.timestamp!), temp.value as double, ); }).toList();
之后就可以用这个列表渲染折线图或其他类型的图表。
内容的提问来源于stack exchange,提问作者Parithi
相关产品推荐
相关产品推荐

