首页 > 解决方案 > 如何用 Flutter 解析动态 JSON?

问题描述

我不明白如何解析从 firebase 获得的 JSON 文件。

这是 JSON 文件的格式

{
  "water" : {
    "-MnRJkFC3--ZOTmpF1xN" : {
      "milliliters" : 0.14,
      "time" : "16:26:25"
    },
    "-MnRJkZRwZYEInHfSKIY" : {
      "milliliters" : 48.83,
      "time" : "16:26:25"
    },
    "-MnRJksES18hY765rxxq" : {
      "milliliters" : 41.44,
      "time" : "16:26:25"
    },
    "-MnRJlDn6o4RmiGRJS-E" : {
      "milliliters" : 11.37,
      "time" : "16:26:25"
    }
  }
}

这就是我阅读 JSON 文件的方式

Future loadSalesData() async {
  final String jsonString = await getJsonFromFirebase();
  final dynamic jsonResponse = json.decode(jsonString);
  for (Map<String, dynamic> i in jsonResponse)
    chartData.add(SalesData.fromJson(i));
  }

getJsonFromFirebase() 看起来像这样:

Future<String> getJsonFromFirebase() async {
  String url =
      "https://emailpassword. . .seio.com/water.json";
  http.Response response = await http.get(Uri.parse(url));
  return response.body;
}

当您单击链接时,它会将您发送到如下所示的 JSON 文件

{
    "-Mnbk2ye2P8bfpaQvNaU": {
        "milliliters": 0.0,
        "time": "18:07:00"
    },
    "-Mnbk6wd-wJze8P0JknK": {
        "milliliters": 0.12,
        "time": "18:07:00"
    },
    "-Mnbk7Ek629vgBu-MiLg": {
        "milliliters": 44.91,
        "time": "18:07:00"
    },
    "-Mnbk7bPuzqwsz9d5nm6": {
        "milliliters": 5.43,
        "time": "18:07:00"
    },
    "-Mnbk7v7MADi7YzEbeFI": {
        "milliliters": 24.54,
        "time": "18:07:00"
    },
    "-Mnbk8DGfqswckdsA1qP": {
        "milliliters": 47.58,
        "time": "18:07:00"
    },
    "-Mnbk8Xw2kJPxLrqCl6h": {
        "milliliters": 13.98,
        "time": "18:07:00"
    }
}

我得到错误

_InternalLinkedHashMap<String, dynamic>' 不是“Iterable”类型的子类型

标签: jsonfirebaseflutterdartfirebase-realtime-database

解决方案


随着您收到的 JSON 的形状,json.decode将返回一个Map<String, dynamic>(更具体地说是专业化的实例_InternalLinkedHashMap<String, dynamic>)。这种类型没有实现Iterable,因此您不能直接使用for-in构造对其进行迭代,而这正是您在运行时得到的确切错误。

根据构建SalesData实例所需的内容,您有两种选择:

  • 遍历entries属性,如果您需要key每个项目("-Mnbk2ye2P8bfpaQvNaU""-Mnbk6wd-wJze8P0JknK"),否则
  • 迭代values属性,如果你不

参赛作品

迭代:
for (MapEntry<String, dynamic> i in jsonResponse.entries) {
  chartData.add(SalesData.fromJson(i));
}
SalesData.fromJson
SalesData.fromJson(MapEntry<String, dynamic> data) {
  id = data.key;
  milliliters = data.value['milliliters'];
  time = data.value['time'];
}

价值观

迭代:
for (Map<String, dynamic> i in jsonResponse.values) {
  chartData.add(SalesData.fromJson(i));
}
SalesData.fromJson
SalesData.fromJson(Map<String, dynamic> data) {
  milliliters = data['milliliters'];
  time = data['time'];
}

类型推断

此外,无论您决定如何迭代Map实例,您都可以利用 Dart 的类型推断稍微清理代码,因此(假设您正在迭代条目)loadSalesData可能变为:

Future loadSalesData() async {
  final jsonString = await getJsonFromFirebase();
  final jsonResponse = json.decode(jsonString);

  for (final i in jsonResponse.entries) {
    chartData.add(SalesData.fromJson(i));
  }
}

getJsonFromFirebase可能成为:

Future<String> getJsonFromFirebase() async {
  final url = "http://localhost:8080/data.json";
  final response = await http.get(Uri.parse(url));
  return response.body;
}

推荐阅读