【问题标题】:Parse JSON to List in Dart将 JSON 解析为 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&params=$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,
    };
}

【问题讨论】:

    标签: json list flutter parsing dart


    【解决方案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&lt;dynamic&gt;。然后您可以将其传递给解析方法并遍历元素。

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-17
      • 1970-01-01
      • 1970-01-01
      • 2019-10-26
      • 1970-01-01
      • 2020-11-25
      相关资源
      最近更新 更多