Search code examples
jsonflutterdartjsonp

Unhandled Exception: NoSuchMethodError: The method '[]' was called on null (json parse)


i m trying to parse this json which print 'confirmed'

{
  "Delhi": {
    "districtData": {
      "East Delhi": {
        "confirmed": 1,
        "lastupdatedtime": ""
      },
      "South West Delhi": {
        "confirmed": 3,
        "lastupdatedtime": ""
      },
      "West Delhi": {
        "confirmed": 2,
        "lastupdatedtime": ""
      },
      "North Delhi": {
        "confirmed": 3,
        "lastupdatedtime": ""
      },
      "New Delhi": {
        "confirmed": 3,
        "lastupdatedtime": ""
      },
      "South Delhi": {
        "confirmed": 2,
        "lastupdatedtime": ""
      },
      "North East Delhi": {
        "confirmed": 1,
        "lastupdatedtime": ""
      },
      "North West Delhi": {
        "confirmed": 3,
        "lastupdatedtime": ""
      },
      "Unknown": {
        "confirmed": 53,
        "lastupdatedtime": ""
      },
      "Delhi": {
        "confirmed": 1,
        "lastupdatedtime": ""
      }
    }
  }
}

https://api.covid19india.org/state_district_wise.json is actual json data and deserialized only delhi data because i want to test it whether it is right or wrong. It is as

class IndiaState {
  Delhi delhi;

  IndiaState({
    this.delhi,
  });

  factory IndiaState.fromJson(Map<String, dynamic> json) => IndiaState(
    delhi: Delhi.fromJson(json["Delhi"]),
  );
}

class Delhi {
  DelhiDistrictData districtData;

  Delhi({
    this.districtData,
  });

  factory Delhi.fromJson(Map<String, dynamic> json) => Delhi(
    districtData: DelhiDistrictData.fromJson(json["districtData"]),
  );
}

class DelhiDistrictData {
  DelhiValue eastDelhi;
  DelhiValue southWestDelhi;
  DelhiValue westDelhi;
  DelhiValue delhi;
  DelhiValue southDelhi;
  DelhiValue northEastDelhi;
  DelhiValue northDelhi;
  DelhiValue northWestDelhi;
  DelhiValue unknown;
  DelhiValue newDelhi;

  DelhiDistrictData({
    this.eastDelhi,
    this.southWestDelhi,
    this.westDelhi,
    this.delhi,
    this.southDelhi,
    this.northEastDelhi,
    this.northDelhi,
    this.northWestDelhi,
    this.unknown,
    this.newDelhi,
  });

  factory DelhiDistrictData.fromJson(Map<String, dynamic> json) => DelhiDistrictData(
    eastDelhi: DelhiValue.fromJson(json["East Delhi"]),
    southWestDelhi: DelhiValue.fromJson(json["South West Delhi"]),
    westDelhi: DelhiValue.fromJson(json["West Delhi"]),
    delhi: DelhiValue.fromJson(json["Delhi"]),
    southDelhi: DelhiValue.fromJson(json["South Delhi"]),
    northEastDelhi: DelhiValue.fromJson(json["North East Delhi"]),
    northDelhi: DelhiValue.fromJson(json["North Delhi"]),
    northWestDelhi: DelhiValue.fromJson(json["North West Delhi"]),
    newDelhi: DelhiValue.fromJson(json["New Delhi"]),
    unknown: DelhiValue.fromJson(json["Unknown"]),
  );
}

class DelhiValue {
  int confirmed;
  String lastupdatedtime;


  DelhiValue({
    this.confirmed,
    this.lastupdatedtime,
  });

  factory DelhiValue.fromJson(Map<String, dynamic> json) => DelhiValue(
    confirmed: json['confirmed'],
    lastupdatedtime: json["lastupdatedtime"],
  );
}

now i am trying to print the confirmed result any one district of delhi as

  @override
  void initState() {
    // TODO: implement initState
    setState(() {
      isLoading = true;
    });

    givenFunction();

    setState(() {
      isLoading = false;
    });
  }

  Future givenFunction() async {
    final httpRequest = await http.get(districtAPI);
    final json = jsonDecode(httpRequest.body);
    IndiaState firstObject = new IndiaState.fromJson(json);
    print(firstObject.delhi.districtData.eastDelhi.confirmed.toString());
  }

Now here comes the error when i tried to print eastDelhi confirmed data

E/flutter ( 5895): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method '[]' was called on null.
E/flutter ( 5895): Receiver: null
E/flutter ( 5895): Tried calling: []("confirmed")
E/flutter ( 5895): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
E/flutter ( 5895): #1      new DelhiValue.fromJson (package:coraona2903/models/district_state.dart:77:20)
E/flutter ( 5895): #2      new DelhiDistrictData.fromJson (package:coraona2903/models/district_state.dart:54:23)
E/flutter ( 5895): #3      new Delhi.fromJson (package:coraona2903/models/district_state.dart:21:37)
E/flutter ( 5895): #4      new IndiaState.fromJson (package:coraona2903/models/district_state.dart:9:18)
E/flutter ( 5895): #5      Covid19ScreenState.givenFunction (package:coraona2903/screens/covid_19_screen.dart:37:34)
E/flutter ( 5895): <asynchronous suspension>

Solution

  • Just Check the modified code :

    Following is the local json that you provided:

    {
        "Delhi": {
          "districtData": {
            "East Delhi": {
              "confirmed": 1,
              "lastupdatedtime": ""
            },
            "South West Delhi": {
              "confirmed": 3,
              "lastupdatedtime": ""
            },
            "West Delhi": {
              "confirmed": 2,
              "lastupdatedtime": ""
            },
            "North Delhi": {
              "confirmed": 3,
              "lastupdatedtime": ""
            },
            "New Delhi": {
              "confirmed": 3,
              "lastupdatedtime": ""
            },
            "South Delhi": {
              "confirmed": 2,
              "lastupdatedtime": ""
            },
            "North East Delhi": {
              "confirmed": 1,
              "lastupdatedtime": ""
            },
            "North West Delhi": {
              "confirmed": 3,
              "lastupdatedtime": ""
            },
            "Unknown": {
              "confirmed": 53,
              "lastupdatedtime": ""
            },
            "Delhi": {
              "confirmed": 1,
              "lastupdatedtime": ""
            }
          }
        }
      }
    

    Later i have created a model class for that :

    // To parse this JSON data, do
    //
    //     final indiaState = indiaStateFromJson(jsonString);
    
    import 'dart:convert';
    
    IndiaState indiaStateFromJson(String str) => IndiaState.fromJson(json.decode(str));
    
    String indiaStateToJson(IndiaState data) => json.encode(data.toJson());
    
    class IndiaState {
        Delhi delhi;
    
        IndiaState({
            this.delhi,
        });
    
        factory IndiaState.fromJson(Map<String, dynamic> json) => IndiaState(
            delhi: Delhi.fromJson(json["Delhi"]),
        );
    
        Map<String, dynamic> toJson() => {
            "Delhi": delhi.toJson(),
        };
    }
    
    class Delhi {
        Map<String, DistrictDatum> districtData;
    
        Delhi({
            this.districtData,
        });
    
        factory Delhi.fromJson(Map<String, dynamic> json) => Delhi(
            districtData: Map.from(json["districtData"]).map((k, v) => MapEntry<String, DistrictDatum>(k, DistrictDatum.fromJson(v))),
        );
    
        Map<String, dynamic> toJson() => {
            "districtData": Map.from(districtData).map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
        };
    }
    
    class DistrictDatum {
        int confirmed;
        String lastupdatedtime;
    
        DistrictDatum({
            this.confirmed,
            this.lastupdatedtime,
        });
    
        factory DistrictDatum.fromJson(Map<String, dynamic> json) => DistrictDatum(
            confirmed: json["confirmed"],
            lastupdatedtime: json["lastupdatedtime"],
        );
    
        Map<String, dynamic> toJson() => {
            "confirmed": confirmed,
            "lastupdatedtime": lastupdatedtime,
        };
    }
    

    below is the main file i have shown your data in a listview check it out :

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:sample_project_for_api/model.dart';
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      bool isLoading = false;
      List<Cities> citilesList = List();
    
      // here i have taken the  json locally which you posted on stack 
      Future<String> loadFromAssets() async {
        return await rootBundle.loadString('json/parse.json');
      }
    
      @override
      void initState() {
        super.initState();
        givenFunction();
      }
    
      Future givenFunction() async {
        setState(() {
          isLoading = true;
        });
    
        //final httpRequest = await http.get(districtAPI);
        //final json = jsonDecode(httpRequest.body);
        // you can make the http call above just uncomment is and comment the below line
        String jsonString = await loadFromAssets();
        // Here you can just replace down your httpRequest.body with jsonString
        final indiaState = indiaStateFromJson(jsonString);
        indiaState.delhi.districtData.forEach((key, value) {
          // This column is show you the values are getting fetched and printed below
          print('This is the key : ' + key);
          print('Confirmed :' + value.confirmed.toString());
          citilesList.add(Cities(key, value.confirmed));
        });
        setState(() {
          isLoading = false;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: isLoading
                ? CircularProgressIndicator()
                : ListView.builder(
                    itemCount: citilesList.length,
                    itemBuilder: (BuildContext context, int index) {
                      return Container(
                        child: Card(
                          margin:
                              EdgeInsets.symmetric(vertical: 10, horizontal: 10),
                          child: Padding(
                            padding: const EdgeInsets.all(15.0),
                            child: Row(
                              children: <Widget>[
                                Text(citilesList[index].state + ": "),
                                Text(citilesList[index].confirmed.toString())
                              ],
                            ),
                          ),
                        ),
                      );
                    },
                  ),
          ),
        );
      }
    }
    
    void main() {
      runApp(HomePage());
    }
    
    class Cities {
      final String state;
      final int confirmed;
    
      Cities(this.state, this.confirmed);
    }
    
    

    Just added a sample image for the data fetch items: enter image description here Let me know if it works