json - 如何在 Flutter 中循环输入 json
问题描述
我从 API 获取数据作为 xml 并通过 xml2json 包将其转换为 json。这里是xml格式;
<scores sport="soccer" ts="1589803352">
<category name="Germany: Bundesliga" gid="1229" id="1229">
<matches>
<match status="18:30" date="May 18" formatted_date="18.05.2020" time="18:30" venue="" static_id="2630549" fix_id="3126153" id="3429740">
</match>
</matches>
</category>
<category name="Turkmenistan: Yokary Liga" gid="2704" id="2704">
<matches>
<match status="14:00" date="May 18" formatted_date="18.05.2020" time="14:00" venue="" static_id="2806325" fix_id="3313495" id="3473381">
</match>
<match status="13:00" date="May 18" formatted_date="18.05.2020" time="13:00" venue="" static_id="2806327" fix_id="3313497" id="3473380">
</match>
<match status="12:15" date="May 18" formatted_date="18.05.2020" time="12:15" venue="" static_id="2806326" fix_id="3313496" id="3473382">
</match>
<match status="12:30" date="May 19" formatted_date="19.05.2020" time="12:30" venue="" static_id="2806328" fix_id="3313498" id="3473383">
</match>
</matches>
</category>
这是在json转换之后;
flutter: {name: Germany: Bundesliga, gid: 1229, id: 1229, matches: {match: {status: 18:30, date: May 18, formatted_date: 18.05.2020, time: 18:30, venue: , static_id: 2630549, fix_id: 3126153, id: 3429740, localteam: {name: Werder Bremen, goals: ?, id: 10677}, visitorteam: {name: Bayer Leverkusen, goals: ?, id: 10281}, events: {}, ht: {score: }, odds: {ts: , type: [{value: Match Winner, stop: False, id: 1, bookmaker: [{name: bwin, stop: False, ts: 1589802984, id: 2, odd: [{name: Home, value: 4.50}, {name: Draw, value: 4.10}, {name: Away, value: 1.72}]}, {name: 10Bet, stop: False, ts: 1589807232, id: 14, odd: [{name: Home, value: 4.45}, {name: Draw, value: 3.95}, {name: Away, value: 1.80}]}, {name: bet365, stop: False, ts: 1589803729, id: 16, odd: [{name: Home, value: 4.33}, {name: Draw, value: 4.00}, {name: Away, value: 1.75}]}, {name: Marathon, stop: False, ts: 1589806921, id: 17, odd: [{name: Home, value: 4.55}, {name: Draw, value: 4.20}, {name: Away, value: 1.83}]}, {name: Unibet, stop: False<…>
如您所见,有一些类别是联赛。每个类别可能有不同数量的匹配。例如,在第一类(德国)中,只有一个匹配项。我可以毫无问题地获得它的属性。第二类(土库曼斯坦)有4场比赛。当我的 for 循环进入该类别时出现错误,因为有多个记录。我尝试了一个内部循环,但我收到错误消息说 String 不是 int of index 的子类型。
这就是我所做的;
xml2json.parse(response.body);
var jsonData = xml2json.toGData();
if (response.statusCode == 200) {
List<dynamic> result = jsonDecode(jsonData)['scores']['category'];
for (int i = 0; i < result.length; i++) {
print(result[i]); //no problem
print(result[i]['name']); c
print(result[i]['id']); //no problem
print(result[i]['matches'].length); //it returns 1 for all categories, because it counts attributes and only attribute is "match"
print(result[i]['matches']['match']['status']); //no problem until second turn, I got string is not subtype of int error
所以,我的问题是如何正确循环结果[i]['matches']?
解决方案
您可以在下面复制粘贴运行完整代码
第 1 步:您可以将 json 字符串解析为Payload
对象payloadFromJson(jsonData)
,您可以在完整代码中看到Payload
相关类
第 2 步:显示payload.scores.category[1].matches.match[i]["status"]
代码片段
xml2json.parse(xml);
String jsonData = xml2json.toGData();
Payload payload = payloadFromJson(jsonData);
for (int i = 0; i < payload.scores.category[1].matches.match.length; i++) {
print(payload.scores.category[1].matches.match[i]["status"]);
}
输出
I/flutter ( 2182): 14:00
I/flutter ( 2182): 13:00
I/flutter ( 2182): 12:15
I/flutter ( 2182): 12:30
完整代码
import 'package:flutter/material.dart';
import 'package:xml2json/xml2json.dart';
import 'dart:convert';
Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));
String payloadToJson(Payload data) => json.encode(data.toJson());
class Payload {
Scores scores;
Payload({
this.scores,
});
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
scores: Scores.fromJson(json["scores"]),
);
Map<String, dynamic> toJson() => {
"scores": scores.toJson(),
};
}
class Scores {
String sport;
String ts;
List<Category> category;
Scores({
this.sport,
this.ts,
this.category,
});
factory Scores.fromJson(Map<String, dynamic> json) => Scores(
sport: json["sport"],
ts: json["ts"],
category: List<Category>.from(
json["category"].map((x) => Category.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"sport": sport,
"ts": ts,
"category": List<dynamic>.from(category.map((x) => x.toJson())),
};
}
class Category {
String name;
String gid;
String id;
Matches matches;
Category({
this.name,
this.gid,
this.id,
this.matches,
});
factory Category.fromJson(Map<String, dynamic> json) => Category(
name: json["name"],
gid: json["gid"],
id: json["id"],
matches: Matches.fromJson(json["matches"]),
);
Map<String, dynamic> toJson() => {
"name": name,
"gid": gid,
"id": id,
"matches": matches.toJson(),
};
}
class Matches {
dynamic match;
Matches({
this.match,
});
factory Matches.fromJson(Map<String, dynamic> json) => Matches(
match: json["match"],
);
Map<String, dynamic> toJson() => {
"match": match,
};
}
class MatchElement {
String status;
String date;
String formattedDate;
String time;
String venue;
String staticId;
String fixId;
String id;
MatchElement({
this.status,
this.date,
this.formattedDate,
this.time,
this.venue,
this.staticId,
this.fixId,
this.id,
});
factory MatchElement.fromJson(Map<String, dynamic> json) => MatchElement(
status: json["status"],
date: json["date"],
formattedDate: json["formatted_date"],
time: json["time"],
venue: json["venue"],
staticId: json["static_id"],
fixId: json["fix_id"],
id: json["id"],
);
Map<String, dynamic> toJson() => {
"status": status,
"date": date,
"formatted_date": formattedDate,
"time": time,
"venue": venue,
"static_id": staticId,
"fix_id": fixId,
"id": id,
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
Xml2Json xml2json = Xml2Json();
String xml = r'''<scores sport="soccer" ts="1589803352">
<category name="Germany: Bundesliga" gid="1229" id="1229">
<matches>
<match status="18:30" date="May 18" formatted_date="18.05.2020" time="18:30" venue="" static_id="2630549" fix_id="3126153" id="3429740">
</match>
</matches>
</category>
<category name="Turkmenistan: Yokary Liga" gid="2704" id="2704">
<matches>
<match status="14:00" date="May 18" formatted_date="18.05.2020" time="14:00" venue="" static_id="2806325" fix_id="3313495" id="3473381">
</match>
<match status="13:00" date="May 18" formatted_date="18.05.2020" time="13:00" venue="" static_id="2806327" fix_id="3313497" id="3473380">
</match>
<match status="12:15" date="May 18" formatted_date="18.05.2020" time="12:15" venue="" static_id="2806326" fix_id="3313496" id="3473382">
</match>
<match status="12:30" date="May 19" formatted_date="19.05.2020" time="12:30" venue="" static_id="2806328" fix_id="3313498" id="3473383">
</match>
</matches>
</category>
</scores>
''';
void _incrementCounter() {
xml2json.parse(xml);
String jsonData = xml2json.toGData();
Payload payload = payloadFromJson(jsonData);
for (int i = 0; i < payload.scores.category[1].matches.match.length; i++) {
print(payload.scores.category[1].matches.match[i]["status"]);
}
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
推荐阅读
- youtube-api - 使用 YouTube 数据 API 创建的直播流被标记为私有
- sql - 如何创建 SQL 分组小计?
- r - 随机完全区组设计
- php - 价格等级计费周期错误
- google-analytics - 页面部分加载 (cdn.ampproject.org)
- reporting-services - 带有算术问题的 SSRS 表达式
- zapier - Zapier公式镜像和Excel公式
- asp.net-core - IdentityServer4 重定向到注销页面而不是 PostLogoutRedirectUri
- rundeck - Rundeck - 根据 sql 查询结果可选择执行步骤
- java - 使用 Guice 绑定基于输入参数的类实例