首页 > 解决方案 > 由于子类型错误,无法从 Internet 加载 json 数据:列表不是类型 Map

问题描述

我是 Flutter 的新手,我想从 API 获取 json 数据。我正在使用可序列化的 json。

这是我从互联网上获取数据的代码:

import 'dart:async';
import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:flutter_json_widget/flutter_json_widget.dart';

import './JsonDataMeter.dart';



Future<Meter> fetchMeter() async {
  final response = await http.get(
      'the url');
  if (response.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    return Meter.fromJson(jsonDecode(response.body));
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load meter');
  }
}

class MeterList extends StatefulWidget {

  MeterList({Key key, }) : super(key: key);

@override
  _MeterList createState() => _MeterList();
}

class _MeterList extends State<MeterList> {
  Future<Meter> futureMeter;
  @override
  void initState(){
    super.initState();
    futureMeter = fetchMeter();
  }


  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Meter>(
      future: futureMeter,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
            return Text(snapshot.data.address.city);
          } else if (snapshot.hasError) {
          //return Text("${snapshot.error}");
          print(snapshot.error);
        }

        // By default, show a loading spinner.
        return CircularProgressIndicator();
      },
    );
  }

这是我创建类的地方,其中包含 json 数据:

import 'package:json_annotation/json_annotation.dart';


part 'JsonDataMeter.g.dart';

@JsonSerializable(explicitToJson: true)

class Meter{

  Address address;
  List<Apartments> apartments;

  Meter({this.address, this.apartments});

  factory Meter.fromJson(Map<String,dynamic> json) => _$MeterFromJson(json);

  Map<String,dynamic> toJson() => _$MeterToJson(this);
}
@JsonSerializable()
class Address {

  String streetAndNumber;
  int PLZ;
  String city;

  Address({this.streetAndNumber, this.PLZ, this.city});

  factory Address.fromJson(Map<String, dynamic> json) =>
      _$AddressFromJson(json);

  Map<String,dynamic> toJson() => _$AddressToJson(this);
}
@JsonSerializable(explicitToJson: true)
class Apartments{

  Tenants tenants;
  List<AssignedMeter> assignedMeter;
  String id;
  Meters meters;
  String location;
  int area;
  String belongingProperty;
  int v;

  Apartments({this.tenants,this.assignedMeter, this.id, this.meters, this.location, this.area, this.belongingProperty, this.v});

  factory Apartments.fromJson(Map<String,dynamic> json) => _$ApartmentsFromJson(json);

  Map<String,dynamic> toJson() => _$ApartmentsToJson(this);
}
@JsonSerializable()
  class Tenants{

    String id;
    String name;
    String belongingApartment;
    String timeInApartment;
    int prepayment;
    int v;
    UsageTimes usageTimes;
    AssociatedApartments associatedApartments;

    Tenants({this.id,this.name, this.belongingApartment, this.timeInApartment, this.prepayment, this.v, this.usageTimes, this.associatedApartments});

    factory Tenants.fromJson(Map<String,dynamic> json) => _$TenantsFromJson(json);

    Map<String,dynamic> toJson() => _$TenantsToJson(this);
  }

@JsonSerializable()
    class UsageTimes{
        String id;
        String usageTime;
        int usedArea;

        UsageTimes({this.id, this.usageTime, this.usedArea});

        factory UsageTimes.fromJson(Map<String,dynamic> json) => _$UsageTimesFromJson(json);

        Map<String,dynamic> toJson() => _$UsageTimesToJson(this);

    }
@JsonSerializable()
    class AssociatedApartments{

        UsageTimes usageTimes;
        String id;
        String apartmentID;
        String timeInApartment;

        AssociatedApartments({this.usageTimes, this.id, this.apartmentID, this.timeInApartment});

        factory AssociatedApartments.fromJson(Map<String,dynamic> json) => _$AssociatedApartmentsFromJson(json);

        Map<String,dynamic> toJson() => _$AssociatedApartmentsToJson(this);
    }
@JsonSerializable()
  class AssignedMeter{

      String id;
      MeterReadings meterReadings;
      String belongingApartment;
      String meterNumber;
      String meterType;
      int v;

      AssignedMeter({this.id, this.meterReadings, this.belongingApartment, this.meterNumber, this.meterType, this.v});

      factory AssignedMeter.fromJson(Map<String,dynamic> json) => _$AssignedMeterFromJson(json);

      Map<String,dynamic> toJson() => _$AssignedMeterToJson(this);


  }
@JsonSerializable()
    class MeterReadings {

        String id;
        String date;
        String value;

        MeterReadings({this.id, this.date, this.value});

        factory MeterReadings.fromJson(Map<String,dynamic> json) => _$MeterReadingsFromJson(json);

        Map<String,dynamic> toJson() => _$MeterReadingsToJson(this);
    }
@JsonSerializable()
   class Meters{

      String id;
      String dateStart;
      String dateEnd;
      int waterStart;
      int waterEnd;
      int powerStart;
      int powerEnd;

      Meters({this.id, this.dateStart, this.dateEnd, this.waterStart, this.waterEnd, this.powerStart, this.powerEnd});

      factory Meters.fromJson(Map<String,dynamic> json) => _$MetersFromJson(json);

      Map<String,dynamic> toJson() => _$MetersToJson(this);
   }

这是 JsonSerializable 自动生成的代码:

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'JsonDataMeter.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

Meter _$MeterFromJson(Map<String, dynamic> json) {
  return Meter(
    address: json['address'] == null
        ? null
        : Address.fromJson(json['address'] as Map<String, dynamic>),
    apartments: (json['apartments'] as List)
        ?.map((e) =>
            e == null ? null : Apartments.fromJson(e as Map<String, dynamic>))
        ?.toList(),
  );
}

Map<String, dynamic> _$MeterToJson(Meter instance) => <String, dynamic>{
      'address': instance.address,
      'apartments': instance.apartments,
    };

Address _$AddressFromJson(Map<String, dynamic> json) {
  return Address(
    streetAndNumber: json['streetAndNumber'] as String,
    PLZ: json['PLZ'] as int,
    city: json['city'] as String,
  );
}

Map<String, dynamic> _$AddressToJson(Address instance) => <String, dynamic>{
      'streetAndNumber': instance.streetAndNumber,
      'PLZ': instance.PLZ,
      'city': instance.city,
    };

Apartments _$ApartmentsFromJson(Map<String, dynamic> json) {
  return Apartments(
    tenants: json['tenants'] == null
        ? null
        : Tenants.fromJson(json['tenants'] as Map<String, dynamic>),
    assignedMeter: (json['assignedMeter'] as List)
        ?.map((e) => e == null
            ? null
            : AssignedMeter.fromJson(e as Map<String, dynamic>))
        ?.toList(),
    id: json['id'] as String,
    meters: json['meters'] == null
        ? null
        : Meters.fromJson(json['meters'] as Map<String, dynamic>),
    location: json['location'] as String,
    area: json['area'] as int,
    belongingProperty: json['belongingProperty'] as String,
    v: json['v'] as int,
  );
}

Map<String, dynamic> _$ApartmentsToJson(Apartments instance) =>
    <String, dynamic>{
      'tenants': instance.tenants,
      'assignedMeter': instance.assignedMeter,
      'id': instance.id,
      'meters': instance.meters,
      'location': instance.location,
      'area': instance.area,
      'belongingProperty': instance.belongingProperty,
      'v': instance.v,
    };

Tenants _$TenantsFromJson(Map<String, dynamic> json) {
  return Tenants(
    id: json['id'] as String,
    name: json['name'] as String,
    belongingApartment: json['belongingApartment'] as String,
    timeInApartment: json['timeInApartment'] as String,
    prepayment: json['prepayment'] as int,
    v: json['v'] as int,
    usageTimes: json['usageTimes'] == null
        ? null
        : UsageTimes.fromJson(json['usageTimes'] as Map<String, dynamic>),
    associatedApartments: json['associatedApartments'] == null
        ? null
        : AssociatedApartments.fromJson(
            json['associatedApartments'] as Map<String, dynamic>),
  );
}

Map<String, dynamic> _$TenantsToJson(Tenants instance) => <String, dynamic>{
      'id': instance.id,
      'name': instance.name,
      'belongingApartment': instance.belongingApartment,
      'timeInApartment': instance.timeInApartment,
      'prepayment': instance.prepayment,
      'v': instance.v,
      'usageTimes': instance.usageTimes,
      'associatedApartments': instance.associatedApartments,
    };

UsageTimes _$UsageTimesFromJson(Map<String, dynamic> json) {
  return UsageTimes(
    id: json['id'] as String,
    usageTime: json['usageTime'] as String,
    usedArea: json['usedArea'] as int,
  );
}

Map<String, dynamic> _$UsageTimesToJson(UsageTimes instance) =>
    <String, dynamic>{
      'id': instance.id,
      'usageTime': instance.usageTime,
      'usedArea': instance.usedArea,
    };

AssociatedApartments _$AssociatedApartmentsFromJson(Map<String, dynamic> json) {
  return AssociatedApartments(
    usageTimes: json['usageTimes'] == null
        ? null
        : UsageTimes.fromJson(json['usageTimes'] as Map<String, dynamic>),
    id: json['id'] as String,
    apartmentID: json['apartmentID'] as String,
    timeInApartment: json['timeInApartment'] as String,
  );
}

Map<String, dynamic> _$AssociatedApartmentsToJson(
        AssociatedApartments instance) =>
    <String, dynamic>{
      'usageTimes': instance.usageTimes,
      'id': instance.id,
      'apartmentID': instance.apartmentID,
      'timeInApartment': instance.timeInApartment,
    };

AssignedMeter _$AssignedMeterFromJson(Map<String, dynamic> json) {
  return AssignedMeter(
    id: json['id'] as String,
    meterReadings: json['meterReadings'] == null
        ? null
        : MeterReadings.fromJson(json['meterReadings'] as Map<String, dynamic>),
    belongingApartment: json['belongingApartment'] as String,
    meterNumber: json['meterNumber'] as String,
    meterType: json['meterType'] as String,
    v: json['v'] as int,
  );
}

Map<String, dynamic> _$AssignedMeterToJson(AssignedMeter instance) =>
    <String, dynamic>{
      'id': instance.id,
      'meterReadings': instance.meterReadings,
      'belongingApartment': instance.belongingApartment,
      'meterNumber': instance.meterNumber,
      'meterType': instance.meterType,
      'v': instance.v,
    };

MeterReadings _$MeterReadingsFromJson(Map<String, dynamic> json) {
  return MeterReadings(
    id: json['id'] as String,
    date: json['date'] as String,
    value: json['value'] as String,
  );
}

Map<String, dynamic> _$MeterReadingsToJson(MeterReadings instance) =>
    <String, dynamic>{
      'id': instance.id,
      'date': instance.date,
      'value': instance.value,
    };

Meters _$MetersFromJson(Map<String, dynamic> json) {
  return Meters(
    id: json['id'] as String,
    dateStart: json['dateStart'] as String,
    dateEnd: json['dateEnd'] as String,
    waterStart: json['waterStart'] as int,
    waterEnd: json['waterEnd'] as int,
    powerStart: json['powerStart'] as int,
    powerEnd: json['powerEnd'] as int,
  );
}

Map<String, dynamic> _$MetersToJson(Meters instance) => <String, dynamic>{
      'id': instance.id,
      'dateStart': instance.dateStart,
      'dateEnd': instance.dateEnd,
      'waterStart': instance.waterStart,
      'waterEnd': instance.waterEnd,
      'powerStart': instance.powerStart,
      'powerEnd': instance.powerEnd,
    };

最后这是我要获取的 json(不是原始值):

{
  "address": {
    "streetAndNumber": "SomeData",
    "PLZ": 1,
    "city": "SomeData"
  },
  "apartments": [
    {
      "tenants": [
        {
          "_id": "SomeData",
          "name": "SomeData",
          "belongingApartment": "SomeData",
          "timeInApartment": "SomeData",
          "prepayment": 1,
          "__v": 1,
          "usageTimes": [
            {
              "_id": "SomeData",
              "usageTime": "SomeData",
              "usedArea": 1
            }
          ],
          "associatedApartments": [
            {
              "usageTimes": [
                {
                  "_id": "SomeData",
                  "usageTime": "SomeData",
                  "usedArea": 1
                }
              ],
              "_id": "SomeData",
              "apartmentID": "SomeData",
              "timeInApartment": "SomeData"
            }
          ]
        }
      ],
      "assignedMeters": [
        {
          "_id": "SomeData",
          "meterReadings": [
            {
              "_id": "SomeData",
              "date": "SomeData",
              "value": 1
            }
          ],
          "belongingApartment": "SomeData",
          "meterNumber": "SomeData",
          "meterType": "SomeData",
          "__v": 1
        },
        {
          "_id": "SomeData",
          "meterReadings": [
            {
              "_id": "SomeData",
              "date": "SomeData",
              "value": 1
            }
          ],
          "belongingApartment": "SomeData",
          "meterNumber": "SomeData",
          "meterType": "SomeData",
          "__v": 1
        },
        {
          "_id": "SomeData",
          "meterReadings": [
            {
              "_id": "SomeData",
              "date": "SomeData",
              "value": 1
            },
            {
              "_id": "SomeData",
              "date": "SomeData",
              "value": 1
            }
          ],
          "belongingApartment": "SomeData",
          "meterNumber": "SomeData",
          "meterType": "SomeData",
          "__v": 1
        }
      ],
      "_id": "SomeData",
      "meters": [
        {
          "_id": "SomeData",
          "dateStart": "SomeData",
          "dateEnd": "SomeData",
          "waterStart": 1,
          "waterEnd": 1,
          "powerStart": 1,
          "powerEnd": 1
        }
      ],
      "location": "SomeData",
      "area": 1,
      "belongingProperty": "SomeData",
      "__v": 1
    },

我总是得到错误:

I/flutter ( 4626): type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>' in type cast

正如我所说,我是 Flutter 的新手,这可能只是一个非常愚蠢的错误,但请帮助我,我觉得我尝试了一切,但我不知道该怎么做。非常感谢。

标签: jsonapiflutter

解决方案


问题在于您的模型。例如:在公寓模型租户中,仪表应为 List<...> 类型。

在租户模型 usageTimes 中, associatedApartments 应该是 List<..> 类型。在 associatedApartments 模型中,usageTimes 应该是 List<...> 类型。

我使用此链接https://javiercbk.github.io/json_to_dart/从您的 json 生成了一个新的响应模型。

试试看。

class MeterListResponse {
  Address address;
  List<Apartments> apartments;

  MeterListResponse({this.address, this.apartments});

  MeterListResponse.fromJson(Map<String, dynamic> json) {
    address =
        json['address'] != null ? new Address.fromJson(json['address']) : null;
    if (json['apartments'] != null) {
      apartments = new List<Apartments>();
      json['apartments'].forEach((v) {
        apartments.add(new Apartments.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.address != null) {
      data['address'] = this.address.toJson();
    }
    if (this.apartments != null) {
      data['apartments'] = this.apartments.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Address {
  String streetAndNumber;
  int pLZ;
  String city;

  Address({this.streetAndNumber, this.pLZ, this.city});

  Address.fromJson(Map<String, dynamic> json) {
    streetAndNumber = json['streetAndNumber'];
    pLZ = json['PLZ'];
    city = json['city'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['streetAndNumber'] = this.streetAndNumber;
    data['PLZ'] = this.pLZ;
    data['city'] = this.city;
    return data;
  }
}

class Apartments {
  List<Tenants> tenants;
  List<AssignedMeters> assignedMeters;
  String sId;
  List<Meters> meters;
  String location;
  int area;
  String belongingProperty;
  int iV;

  Apartments(
      {this.tenants,
      this.assignedMeters,
      this.sId,
      this.meters,
      this.location,
      this.area,
      this.belongingProperty,
      this.iV});

  Apartments.fromJson(Map<String, dynamic> json) {
    if (json['tenants'] != null) {
      tenants = new List<Tenants>();
      json['tenants'].forEach((v) {
        tenants.add(new Tenants.fromJson(v));
      });
    }
    if (json['assignedMeters'] != null) {
      assignedMeters = new List<AssignedMeters>();
      json['assignedMeters'].forEach((v) {
        assignedMeters.add(new AssignedMeters.fromJson(v));
      });
    }
    sId = json['_id'];
    if (json['meters'] != null) {
      meters = new List<Meters>();
      json['meters'].forEach((v) {
        meters.add(new Meters.fromJson(v));
      });
    }
    location = json['location'];
    area = json['area'];
    belongingProperty = json['belongingProperty'];
    iV = json['__v'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.tenants != null) {
      data['tenants'] = this.tenants.map((v) => v.toJson()).toList();
    }
    if (this.assignedMeters != null) {
      data['assignedMeters'] =
          this.assignedMeters.map((v) => v.toJson()).toList();
    }
    data['_id'] = this.sId;
    if (this.meters != null) {
      data['meters'] = this.meters.map((v) => v.toJson()).toList();
    }
    data['location'] = this.location;
    data['area'] = this.area;
    data['belongingProperty'] = this.belongingProperty;
    data['__v'] = this.iV;
    return data;
  }
}

class Tenants {
  String sId;
  String name;
  String belongingApartment;
  String timeInApartment;
  int prepayment;
  int iV;
  List<UsageTimes> usageTimes;
  List<AssociatedApartments> associatedApartments;

  Tenants(
      {this.sId,
      this.name,
      this.belongingApartment,
      this.timeInApartment,
      this.prepayment,
      this.iV,
      this.usageTimes,
      this.associatedApartments});

  Tenants.fromJson(Map<String, dynamic> json) {
    sId = json['_id'];
    name = json['name'];
    belongingApartment = json['belongingApartment'];
    timeInApartment = json['timeInApartment'];
    prepayment = json['prepayment'];
    iV = json['__v'];
    if (json['usageTimes'] != null) {
      usageTimes = new List<UsageTimes>();
      json['usageTimes'].forEach((v) {
        usageTimes.add(new UsageTimes.fromJson(v));
      });
    }
    if (json['associatedApartments'] != null) {
      associatedApartments = new List<AssociatedApartments>();
      json['associatedApartments'].forEach((v) {
        associatedApartments.add(new AssociatedApartments.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['_id'] = this.sId;
    data['name'] = this.name;
    data['belongingApartment'] = this.belongingApartment;
    data['timeInApartment'] = this.timeInApartment;
    data['prepayment'] = this.prepayment;
    data['__v'] = this.iV;
    if (this.usageTimes != null) {
      data['usageTimes'] = this.usageTimes.map((v) => v.toJson()).toList();
    }
    if (this.associatedApartments != null) {
      data['associatedApartments'] =
          this.associatedApartments.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class UsageTimes {
  String sId;
  String usageTime;
  int usedArea;

  UsageTimes({this.sId, this.usageTime, this.usedArea});

  UsageTimes.fromJson(Map<String, dynamic> json) {
    sId = json['_id'];
    usageTime = json['usageTime'];
    usedArea = json['usedArea'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['_id'] = this.sId;
    data['usageTime'] = this.usageTime;
    data['usedArea'] = this.usedArea;
    return data;
  }
}

class AssociatedApartments {
  List<UsageTimes> usageTimes;
  String sId;
  String apartmentID;
  String timeInApartment;

  AssociatedApartments(
      {this.usageTimes, this.sId, this.apartmentID, this.timeInApartment});

  AssociatedApartments.fromJson(Map<String, dynamic> json) {
    if (json['usageTimes'] != null) {
      usageTimes = new List<UsageTimes>();
      json['usageTimes'].forEach((v) {
        usageTimes.add(new UsageTimes.fromJson(v));
      });
    }
    sId = json['_id'];
    apartmentID = json['apartmentID'];
    timeInApartment = json['timeInApartment'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.usageTimes != null) {
      data['usageTimes'] = this.usageTimes.map((v) => v.toJson()).toList();
    }
    data['_id'] = this.sId;
    data['apartmentID'] = this.apartmentID;
    data['timeInApartment'] = this.timeInApartment;
    return data;
  }
}

class AssignedMeters {
  String sId;
  List<MeterReadings> meterReadings;
  String belongingApartment;
  String meterNumber;
  String meterType;
  int iV;

  AssignedMeters(
      {this.sId,
      this.meterReadings,
      this.belongingApartment,
      this.meterNumber,
      this.meterType,
      this.iV});

  AssignedMeters.fromJson(Map<String, dynamic> json) {
    sId = json['_id'];
    if (json['meterReadings'] != null) {
      meterReadings = new List<MeterReadings>();
      json['meterReadings'].forEach((v) {
        meterReadings.add(new MeterReadings.fromJson(v));
      });
    }
    belongingApartment = json['belongingApartment'];
    meterNumber = json['meterNumber'];
    meterType = json['meterType'];
    iV = json['__v'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['_id'] = this.sId;
    if (this.meterReadings != null) {
      data['meterReadings'] =
          this.meterReadings.map((v) => v.toJson()).toList();
    }
    data['belongingApartment'] = this.belongingApartment;
    data['meterNumber'] = this.meterNumber;
    data['meterType'] = this.meterType;
    data['__v'] = this.iV;
    return data;
  }
}

class MeterReadings {
  String sId;
  String date;
  int value;

  MeterReadings({this.sId, this.date, this.value});

  MeterReadings.fromJson(Map<String, dynamic> json) {
    sId = json['_id'];
    date = json['date'];
    value = json['value'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['_id'] = this.sId;
    data['date'] = this.date;
    data['value'] = this.value;
    return data;
  }
}

class Meters {
  String sId;
  String dateStart;
  String dateEnd;
  int waterStart;
  int waterEnd;
  int powerStart;
  int powerEnd;

  Meters(
      {this.sId,
      this.dateStart,
      this.dateEnd,
      this.waterStart,
      this.waterEnd,
      this.powerStart,
      this.powerEnd});

  Meters.fromJson(Map<String, dynamic> json) {
    sId = json['_id'];
    dateStart = json['dateStart'];
    dateEnd = json['dateEnd'];
    waterStart = json['waterStart'];
    waterEnd = json['waterEnd'];
    powerStart = json['powerStart'];
    powerEnd = json['powerEnd'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['_id'] = this.sId;
    data['dateStart'] = this.dateStart;
    data['dateEnd'] = this.dateEnd;
    data['waterStart'] = this.waterStart;
    data['waterEnd'] = this.waterEnd;
    data['powerStart'] = this.powerStart;
    data['powerEnd'] = this.powerEnd;
    return data;
  }
}

推荐阅读