将 JSON 解析为 Dart 中的列表
Posted
技术标签:
【中文标题】将 JSON 解析为 Dart 中的列表【英文标题】:Parse JSON to List in Dart 【发布时间】:2021-03-22 23:42:29 【问题描述】:我正在尝试从天气 API 解析一些复杂的 JSON,并将其显示在列表视图中。我使用 quickType 为我生成模型,但似乎无法将数据解析为列表。我相当确定错误的主要部分是我在解析服务文件中的数据时的逻辑,因为来自 API 的数据具有复杂的结构,我不知道如何解析。由于 API 数据,它分为 2 个地图或列表?小时和元。因此有一个额外的课程。请帮帮我。
这是服务/解析文件:
import 'weather_model.dart';
import 'package:http/http.dart' as http;
import 'dart:io';
class Service
static const lat = '-33.7506';
static const lng = '18.4401';
static const params =
'swellDirection,windSpeed,windDirection,wavePeriod,waveHeight,airTemperature';
static Future<List<Hour>> getConditions() async
try
final response = await http.get(
Uri.encodeFull(
'https://api.stormglass.io/v2/weather/point?lat=$lat&lng=$lng¶ms=$params&start=2020-12-11&end=2020-12-12'),
headers:
HttpHeaders.authorizationHeader:
'exampleapi'
);
if (200 == response.statusCode)
final conditions = conditionsFromJson(response.body);
print(response.body);
return conditions.hours;
catch (e)
print('Not working');
return List<Hour>();
这是我的主文件:
import 'package:flutter/material.dart';
import 'package:moreapi_practise/weather_model.dart';
import 'Service.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'My API Practice'),
);
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
List<Hour> _conditions;
bool _loading;
@override
void initState()
super.initState();
_loading = true;
Service.getConditions().then((conditions)
_conditions = conditions;
_loading = false;
);
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Conditions'),
),
body: Container(child: ListView.builder(itemBuilder: (context, index)
Hour condition = _conditions[index];
return ListTile(
title: Text('$condition.airTemperature'),
);
)),
);
然后是我的模型:
// To parse this JSON data, do
//
// final conditions = conditionsFromJson(jsonString);
import 'dart:convert';
Conditions conditionsFromJson(String str) => Conditions.fromJson(json.decode(str));
String conditionsToJson(Conditions data) => json.encode(data.toJson());
class Conditions
Conditions(
this.hours,
this.meta,
);
List<Hour> hours;
Meta meta;
factory Conditions.fromJson(Map<String, dynamic> json) => Conditions(
hours: List<Hour>.from(json["hours"].map((x) => Hour.fromJson(x))),
meta: Meta.fromJson(json["meta"]),
);
Map<String, dynamic> toJson() =>
"hours": List<dynamic>.from(hours.map((x) => x.toJson())),
"meta": meta.toJson(),
;
class Hour
Hour(
this.airTemperature,
this.swellDirection,
this.time,
this.waveHeight,
this.wavePeriod,
this.windDirection,
this.windSpeed,
);
AirTemperature airTemperature;
SwellDirection swellDirection;
DateTime time;
SwellDirection waveHeight;
SwellDirection wavePeriod;
SwellDirection windDirection;
SwellDirection windSpeed;
factory Hour.fromJson(Map<String, dynamic> json) => Hour(
airTemperature: AirTemperature.fromJson(json["airTemperature"]),
swellDirection: SwellDirection.fromJson(json["swellDirection"]),
time: DateTime.parse(json["time"]),
waveHeight: SwellDirection.fromJson(json["waveHeight"]),
wavePeriod: SwellDirection.fromJson(json["wavePeriod"]),
windDirection: SwellDirection.fromJson(json["windDirection"]),
windSpeed: SwellDirection.fromJson(json["windSpeed"]),
);
Map<String, dynamic> toJson() =>
"airTemperature": airTemperature.toJson(),
"swellDirection": swellDirection.toJson(),
"time": time.toIso8601String(),
"waveHeight": waveHeight.toJson(),
"wavePeriod": wavePeriod.toJson(),
"windDirection": windDirection.toJson(),
"windSpeed": windSpeed.toJson(),
;
class AirTemperature
AirTemperature(
this.noaa,
this.sg,
);
double noaa;
double sg;
factory AirTemperature.fromJson(Map<String, dynamic> json) => AirTemperature(
noaa: json["noaa"].toDouble(),
sg: json["sg"].toDouble(),
);
Map<String, dynamic> toJson() =>
"noaa": noaa,
"sg": sg,
;
class SwellDirection
SwellDirection(
this.icon,
this.meteo,
this.noaa,
this.sg,
);
double icon;
double meteo;
double noaa;
double sg;
factory SwellDirection.fromJson(Map<String, dynamic> json) => SwellDirection(
icon: json["icon"].toDouble(),
meteo: json["meteo"] == null ? null : json["meteo"].toDouble(),
noaa: json["noaa"].toDouble(),
sg: json["sg"].toDouble(),
);
Map<String, dynamic> toJson() =>
"icon": icon,
"meteo": meteo == null ? null : meteo,
"noaa": noaa,
"sg": sg,
;
class Meta
Meta(
this.cost,
this.dailyQuota,
this.end,
this.lat,
this.lng,
this.params,
this.requestCount,
this.start,
);
int cost;
int dailyQuota;
String end;
double lat;
double lng;
List<String> params;
int requestCount;
String start;
factory Meta.fromJson(Map<String, dynamic> json) => Meta(
cost: json["cost"],
dailyQuota: json["dailyQuota"],
end: json["end"],
lat: json["lat"].toDouble(),
lng: json["lng"].toDouble(),
params: List<String>.from(json["params"].map((x) => x)),
requestCount: json["requestCount"],
start: json["start"],
);
Map<String, dynamic> toJson() =>
"cost": cost,
"dailyQuota": dailyQuota,
"end": end,
"lat": lat,
"lng": lng,
"params": List<dynamic>.from(params.map((x) => x)),
"requestCount": requestCount,
"start": start,
;
【问题讨论】:
【参考方案1】:请检查您的 main.dart 的工作代码。问题是您在 initState 中调用 Service.getConditions。 Service.getConditions 是一个未来,在将数据加载到 ListView 之前,您没有等待 Future 完成。下面的代码将向您展示如何等待 Future 完成然后加载数据的一种方法。在 ListView 中,您显示的是 condition.airTemperature,所以我在那里做了一些更改,现在显示的是 condition.airTemperature.noaa& condition.airTemperature.sg。
import 'package:flutter/material.dart';
import 'package:moreapi_practise/weather_model.dart';
import 'Service.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'My API Practice'),
);
class MyHomePage extends StatefulWidget
const MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
List<Hour> _conditions;
bool _loading;
Future myFuture;
Future _getService() async
await Service.getConditions().then((conditions)
setState(()
_conditions = conditions;
_loading = false;
);
);
@override
void initState()
super.initState();
_loading = true;
myFuture = _getService();
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Conditions'),
),
body: _loading
? const Center(
child: CircularProgressIndicator(),
)
: Container(
child: ListView.builder(
itemCount: _conditions.length,
itemBuilder: (context, index)
final Hour condition = _conditions[index];
return ListTile(
title: Text(
'$condition.airTemperature.noaa $condition.airTemperature.sg'),
);
,
),
),
);
【讨论】:
哇,这很好用,谢谢,我完全看错了方向,对 dart 和 JSON 来说都是新手,再次感谢! 当我看到一个涉及未来的初学者问题时,我首先检查的是他们是否在等待未来的回归。如果您认为它解决了您的问题,也请支持答案。谢谢。 我下次会知道,而且我的声誉分数太低,无法公开显示:(【参考方案2】:试试json['hours’] as List<dynamic>
。然后您可以将其传递给解析方法并遍历元素。
List<Hour> hours = parseHourList(json['hours'] as List<dynamic>);
// ...
List<Hour> parseHourList(List<dynamic> jsonList)
final List<Hour> list = [];
for(dynamic element in jsonList)
final Hour hour = Hour.fromJson(element as Map<String, dynamic>);
list.add(hour);
return list;
【讨论】:
以上是关于将 JSON 解析为 Dart 中的列表的主要内容,如果未能解决你的问题,请参考以下文章
从 Dart 中的 json 文件中获取嵌套列表内容,但返回“'FormContent'的实例”