首页 > 解决方案 > 如何在 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<…&gt;

如您所见,有一些类别是联赛。每个类别可能有不同数量的匹配。例如,在第一类(德国)中,只有一个匹配项。我可以毫无问题地获得它的属性。第二类(土库曼斯坦)有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']?

标签: jsonloopsflutterdart

解决方案


您可以在下面复制粘贴运行完整代码
第 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),
      ),
    );
  }
}

推荐阅读