Home > Net >  i have problem to consume the complex Json file
i have problem to consume the complex Json file

Time:02-23

I convert the JSON file to dart using a quiqtype generator when a consume a simple object they work fine but when I want to consume a list inside an object I get many errors ('type null is not subtyped of type Map<string, dynamic>")

this is the JSON file

[{"id":48,"name":"Golf 7 DG-382-ED","status":"offline","position":null,"vehicleId":245,"driver":null,"motionState":"untracked","motionTime":null,"immobileFeature":false,"geofenceIds":null,"deviceState":null},{"id":136,"name":"GOLF 7 FJ-468-TH","status":"online","position":{"fixTime":"2022-02-21T08:51:40.000 00:00","speed":0.0,"bearing":0.0,"address":"51 Rue de Verdun, Suresnes, Île-de-France","latlng":[48.8734666,2.2296383],"attributes":{"alarm":null,"immobile":null,"odometer":1.2178792E7,"fuelUsed":1195.45,"avgFuelUsed":6.48,"ignition":false,"coolantTemp":0.0,"power":12.51,"battery":3.96}},"vehicleId":307,"driver":{"name":"Jalloul KAROUIA","phone":"0033615275389"},"motionState":"parked","motionTime":"2022-02-21T08:51:40.000 00:00","immobileFeature":false,"geofenceIds":[],"deviceState":{"parkingAddress":"51 Rue de Verdun, Suresnes, Île-de-France","tracks":[],"traveldistance":0.0,"travelingDuration":0}}]

and this is the dart file

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

import 'dart:convert';

Future<List<Vehicle>> fetchVehicle() async {
  final response = await http.get(
    Uri.parse(''),
    headers: {
      "Authorization":
          ""
    },
  );

  if (response.statusCode == 200) {
    final parsed = json.decode(response.body).cast<Map<String, dynamic>>();

    return parsed.map<Vehicle>((json) => Vehicle.fromJson(json)).toList();
  } else {
    throw Exception('Failed to load album');
  }
}

List<Vehicle> vehicleFromJson(String str) =>
    List<Vehicle>.from(json.decode(str).map((x) => Vehicle.fromJson(x)));

class Vehicle {
  Vehicle({
    required this.id,
    required this.name,
    required this.status,
    required this.position,
    required this.vehicleId,
    required this.driver,
    required this.motionState,
    required this.motionTime,
    required this.immobileFeature,
    required this.geofenceIds,
    required this.deviceState,
  });

  int id;
  String name;
  String status;
  Position position;
  int vehicleId;
  Driver driver;
  String motionState;
  DateTime motionTime;
  bool immobileFeature;
  List<dynamic> geofenceIds;
  DeviceState deviceState;

  factory Vehicle.fromJson(Map<String, dynamic> json) => Vehicle(
        id: json["id"],
        name: json["name"],
        status: json["status"],
        position: Position.fromJson(json["position"]),
        vehicleId: json["vehicleId"],
        driver: Driver.fromJson(json["driver"]),
        motionState: json["motionState"],
        motionTime: json["motionTime"] ?? new DateTime(2022, 12, 11),
        immobileFeature: json["immobileFeature"],
        geofenceIds: json["geofenceIds"] ?? [],
        deviceState: DeviceState.fromJson(json["deviceState"]),
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "name": name,
        "status": status,
        "position": position.toJson(),
        "vehicleId": vehicleId,
        "driver": driver.toJson(),
        "motionState": motionState,
        "motionTime": motionTime.toIso8601String(),
        "immobileFeature": immobileFeature,
        "geofenceIds": List<dynamic>.from(geofenceIds.map((x) => x)),
        "deviceState": deviceState.toJson(),
      };
}

class DeviceState {
  DeviceState({
    required this.parkingAddress,
    required this.tracks,
    required this.traveldistance,
    required this.travelingDuration,
  });

  String parkingAddress;
  List<dynamic> tracks;
  int traveldistance;
  int travelingDuration;

  factory DeviceState.fromJson(Map<String, dynamic> json) => DeviceState(
        parkingAddress: json["parkingAddress"],
        tracks: List<dynamic>.from(json["tracks"].map((x) => x)),
        traveldistance: json["traveldistance"],
        travelingDuration: json["travelingDuration"],
      );

  Map<String, dynamic> toJson() => {
        "parkingAddress": parkingAddress,
        "tracks": List<dynamic>.from(tracks.map((x) => x)),
        "traveldistance": traveldistance,
        "travelingDuration": travelingDuration,
      };
}

class Driver {
  Driver({
    required this.name,
    required this.phone,
  });

  String name;
  String phone;

  factory Driver.fromJson(Map<String, dynamic> json) => Driver(
        name: json["name"],
        phone: json["phone"],
      );

  Map<String, dynamic> toJson() => {
        "name": name,
        "phone": phone,
      };
}

class Position {
  Position({
    required this.fixTime,
    required this.speed,
    required this.bearing,
    required this.address,
    required this.latlng,
    required this.attributes,
  });

  DateTime fixTime;
  int speed;
  int bearing;
  String address;
  List<double> latlng;
  Attributes attributes;

  factory Position.fromJson(Map<String, dynamic> json) => Position(
        fixTime: DateTime.parse(json["fixTime"]),
        speed: json["speed"],
        bearing: json["bearing"],
        address: json["address"],
        latlng: List<double>.from(json["latlng"].map((x) => x.toDouble())),
        attributes: Attributes.fromJson(json["attributes"]),
      );

  Map<String, dynamic> toJson() => {
        "fixTime": fixTime.toIso8601String(),
        "speed": speed,
        "bearing": bearing,
        "address": address,
        "latlng": List<dynamic>.from(latlng.map((x) => x)),
        "attributes": attributes.toJson(),
      };
}

class Attributes {
  Attributes({
    this.alarm,
    this.immobile,
    required this.odometer,
    required this.fuelUsed,
    required this.avgFuelUsed,
    required this.ignition,
    required this.coolantTemp,
    required this.power,
    required this.battery,
  });

  dynamic alarm;
  dynamic immobile;
  int odometer;
  double fuelUsed;
  double avgFuelUsed;
  bool ignition;
  int coolantTemp;
  double power;
  double battery;

  factory Attributes.fromJson(Map<String, dynamic> json) => Attributes(
        alarm: json["alarm"],
        immobile: json["immobile"],
        odometer: json["odometer"],
        fuelUsed: json["fuelUsed"].toDouble(),
        avgFuelUsed: json["avgFuelUsed"].toDouble(),
        ignition: json["ignition"],
        coolantTemp: json["coolantTemp"],
        power: json["power"].toDouble(),
        battery: json["battery"].toDouble(),
      );

  Map<String, dynamic> toJson() => {
        "alarm": alarm,
        "immobile": immobile,
        "odometer": odometer,
        "fuelUsed": fuelUsed,
        "avgFuelUsed": avgFuelUsed,
        "ignition": ignition,
        "coolantTemp": coolantTemp,
        "power": power,
        "battery": battery,
      };
}

this is how i use the fetched data

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

import 'package:changenotifier/car_screen.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import 'package:changenotifier/models/members.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late Future<List<Vehicle>> futureVehicle;

  @override
  void initState() {
    super.initState();
    futureVehicle = fetchVehicle();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fetch Data Example',
      theme: ThemeData(
        primaryColor: Colors.grey.shade100,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Fetch Data Example'),
        ),
        body: FutureBuilder<List<Vehicle>>(
          future: futureVehicle,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return (ListView.builder(
                itemCount: snapshot.data!.length,
                itemBuilder: (_, index) => GestureDetector(
                  onTap: () => Navigator.of(context).push(
                    MaterialPageRoute(
                      fullscreenDialog: true,
                      // ignore: prefer_const_constructors
                      builder: (context) => carscreen(snapshot.data![index]),
                    ),
                  ),
                  child: Container(
                    margin: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
                    padding: EdgeInsets.all(20.0),
                    decoration: BoxDecoration(
                      color: Colors.grey.shade300,
                      borderRadius: BorderRadius.circular(15.0),
                    ),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          "${snapshot.data![index].name}",
                          style: TextStyle(
                            fontSize: 18.0,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        SizedBox(height: 10),
                        Text("${snapshot.data![index].id}"),
                        SizedBox(height: 10),
                        Text("${snapshot.data![index].status}"),
                        SizedBox(height: 10),
                        Text("${snapshot.data![index].vehicleId}"),
                        SizedBox(height: 10),
                        Text("${snapshot.data![index].motionState}"),
                      ],
                    ),
                  ),
                ),
              ));
            } else {
              return Center(child: CircularProgressIndicator());
            }
          },
        ),
      ),
    );
  }
}

CodePudding user response:

You have to check for the null before parsing it to your model class using a map.

for example:

position: json["position"] == null ? null : Position.fromJson(json["position"]),

Here position in your JSON response is null and it will fail during parsing.

Also, https://app.quicktype.io/ should've generated a model class with these null checks.

EDIT

Adding full generated model class.

// To parse this JSON data, do
//
//     final welcome = welcomeFromJson(jsonString);

import 'dart:convert';

List<Welcome> welcomeFromJson(String str) => List<Welcome>.from(json.decode(str).map((x) => Welcome.fromJson(x)));

String welcomeToJson(List<Welcome> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Welcome {
    Welcome({
        this.id,
        this.name,
        this.status,
        this.position,
        this.vehicleId,
        this.driver,
        this.motionState,
        this.motionTime,
        this.immobileFeature,
        this.geofenceIds,
        this.deviceState,
    });

    int id;
    String name;
    String status;
    Position position;
    int vehicleId;
    Driver driver;
    String motionState;
    DateTime motionTime;
    bool immobileFeature;
    List<dynamic> geofenceIds;
    DeviceState deviceState;

    factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
        id: json["id"],
        name: json["name"],
        status: json["status"],
        position: json["position"] == null ? null : Position.fromJson(json["position"]),
        vehicleId: json["vehicleId"],
        driver: json["driver"] == null ? null : Driver.fromJson(json["driver"]),
        motionState: json["motionState"],
        motionTime: json["motionTime"] == null ? null : DateTime.parse(json["motionTime"]),
        immobileFeature: json["immobileFeature"],
        geofenceIds: json["geofenceIds"] == null ? null : List<dynamic>.from(json["geofenceIds"].map((x) => x)),
        deviceState: json["deviceState"] == null ? null : DeviceState.fromJson(json["deviceState"]),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "name": name,
        "status": status,
        "position": position == null ? null : position.toJson(),
        "vehicleId": vehicleId,
        "driver": driver == null ? null : driver.toJson(),
        "motionState": motionState,
        "motionTime": motionTime == null ? null : motionTime.toIso8601String(),
        "immobileFeature": immobileFeature,
        "geofenceIds": geofenceIds == null ? null : List<dynamic>.from(geofenceIds.map((x) => x)),
        "deviceState": deviceState == null ? null : deviceState.toJson(),
    };
}

class DeviceState {
    DeviceState({
        this.parkingAddress,
        this.tracks,
        this.traveldistance,
        this.travelingDuration,
    });

    String parkingAddress;
    List<dynamic> tracks;
    int traveldistance;
    int travelingDuration;

    factory DeviceState.fromJson(Map<String, dynamic> json) => DeviceState(
        parkingAddress: json["parkingAddress"],
        tracks: List<dynamic>.from(json["tracks"].map((x) => x)),
        traveldistance: json["traveldistance"],
        travelingDuration: json["travelingDuration"],
    );

    Map<String, dynamic> toJson() => {
        "parkingAddress": parkingAddress,
        "tracks": List<dynamic>.from(tracks.map((x) => x)),
        "traveldistance": traveldistance,
        "travelingDuration": travelingDuration,
    };
}

class Driver {
    Driver({
        this.name,
        this.phone,
    });

    String name;
    String phone;

    factory Driver.fromJson(Map<String, dynamic> json) => Driver(
        name: json["name"],
        phone: json["phone"],
    );

    Map<String, dynamic> toJson() => {
        "name": name,
        "phone": phone,
    };
}

class Position {
    Position({
        this.fixTime,
        this.speed,
        this.bearing,
        this.address,
        this.latlng,
        this.attributes,
    });

    DateTime fixTime;
    int speed;
    int bearing;
    String address;
    List<double> latlng;
    Attributes attributes;

    factory Position.fromJson(Map<String, dynamic> json) => Position(
        fixTime: DateTime.parse(json["fixTime"]),
        speed: json["speed"],
        bearing: json["bearing"],
        address: json["address"],
        latlng: List<double>.from(json["latlng"].map((x) => x.toDouble())),
        attributes: Attributes.fromJson(json["attributes"]),
    );

    Map<String, dynamic> toJson() => {
        "fixTime": fixTime.toIso8601String(),
        "speed": speed,
        "bearing": bearing,
        "address": address,
        "latlng": List<dynamic>.from(latlng.map((x) => x)),
        "attributes": attributes.toJson(),
    };
}

class Attributes {
    Attributes({
        this.alarm,
        this.immobile,
        this.odometer,
        this.fuelUsed,
        this.avgFuelUsed,
        this.ignition,
        this.coolantTemp,
        this.power,
        this.battery,
    });

    dynamic alarm;
    dynamic immobile;
    int odometer;
    double fuelUsed;
    double avgFuelUsed;
    bool ignition;
    int coolantTemp;
    double power;
    double battery;

    factory Attributes.fromJson(Map<String, dynamic> json) => Attributes(
        alarm: json["alarm"],
        immobile: json["immobile"],
        odometer: json["odometer"],
        fuelUsed: json["fuelUsed"].toDouble(),
        avgFuelUsed: json["avgFuelUsed"].toDouble(),
        ignition: json["ignition"],
        coolantTemp: json["coolantTemp"],
        power: json["power"].toDouble(),
        battery: json["battery"].toDouble(),
    );

    Map<String, dynamic> toJson() => {
        "alarm": alarm,
        "immobile": immobile,
        "odometer": odometer,
        "fuelUsed": fuelUsed,
        "avgFuelUsed": avgFuelUsed,
        "ignition": ignition,
        "coolantTemp": coolantTemp,
        "power": power,
        "battery": battery,
    };
}

CodePudding user response:

Only you need change model and Api

I am already call this type API you go to my git hub link and understand concept.

API link: https://jsonplaceholder.typicode.com/posts

GitHub link: https://github.com/JayswalViraj/API_With_Model/blob/main/lib/API Helper ( Methods )/api_home.dart

  • Related