flutterdartjsonapi-serialize

Flutter : The getter was called on null (JSON API call)


I've a problem where I know where something went wrong but I can't figure how to solve it. I'm new to the Flutter developpement and I'm trying to create an application. For this application, I need to call an API that return data, but based on what I ask i can have different returns.

Here are two examples :

{
  "name": "Luken",
  "race": "Blood Elf",
  "class": "Death Knight",
  "active_spec_name": "Blood",
  "active_spec_role": "TANK",
  "gender": "male",
  "faction": "horde",
  "achievement_points": 5145,
  "honorable_kills": 0,
  "thumbnail_url": "https://render-eu.worldofwarcraft.com/character/ysondre/200/100426440-avatar.jpg?alt=wow/static/images/2d/avatar/10-0.jpg",
  "region": "eu",
  "realm": "Ysondre",
  "profile_url": "https://raider.io/characters/eu/ysondre/Luken",
  "profile_banner": "hordebanner1",
  "guild": null
} 

Second API return :

{
  "name": "Rakhalar",
  "race": "Zandalari Troll",
  "class": "Druid",
  "active_spec_name": "Guardian",
  "active_spec_role": "TANK",
  "gender": "male",
  "faction": "horde",
  "achievement_points": 5525,
  "honorable_kills": 0,
  "thumbnail_url": "https://render-eu.worldofwarcraft.com/character/illidan/213/142815957-avatar.jpg?alt=wow/static/images/2d/avatar/31-0.jpg",
  "region": "eu",
  "realm": "Illidan",
  "profile_url": "https://raider.io/characters/eu/illidan/Rakhalar",
  "profile_banner": "hordebanner1",
  "guild": {
    "name": "Gueule de Bois",
    "realm": "Illidan"
  }

The main difference between the two returns is the guild key : It can be null. I don't know how to handle it, as it result an error when I'm trying to call for the name or realm value when the character (it's basically information for WoW characters that return the API).

The Class i'm using to serialize the JSON is the following :

class Guild {
  String name;
  String realm;

  Guild({
    this.name,
    this.realm,
  });

  factory Guild.fromJson(Map<String, dynamic> json) => Guild(
        name: json["name"] == null ? null : json["name"],
        realm: json["realm"] == null ? null : json["realm"],
      );

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

And there's the UI part (in case it's something to do in the view side, but I really don't think so.)

class CharacterDetailPage extends StatelessWidget {
  final CharacterDetailArguments args;

  CharacterDetailPage({this.args});

  @override
  Widget build(BuildContext ctxt) {
    return new Scaffold(
      appBar: AppBar(
        title: Text("Detail page for ${args.name}"),
      ),
      body: FutureBuilder<CharacterDetailApi>(
          future: getCharacterDetails(args.name, args.realm, args.region),
          builder: (context, snapshot) {
            return snapshot.hasData
                ? Container(
                        child: 
                          Container(
                            height: 125,
                            child: Column(
                              children: <Widget>[
                                Text(snapshot.data.name, ),
                                Text("<" + snapshot.data.guild.name + ">",),
                                Text(snapshot.data.guild.realm,),
                              ],
                            ),
                          ),
                  )
          }),
    );
  }
}

I'm sure it's a basic issue but I didn't find any relevant information for it yet :(

Edit : There's the code that work, using anonymous function :

Column(
  children: <Widget>[
    Text(snapshot.data.name,),
    if (snapshot.data.guild != null)
      Text("<" + snapshot.data.guild.name +">",),
    if (snapshot.data.guild != null)
      Text(snapshot.data.guild.realm,),
  ],
),

Solution

  • change this code

    Text("<" + snapshot.data.guild.name + ">",),
    Text(snapshot.data.guild.realm,),
    

    to this :

    if (snapshot.data.guild != null) {
       Text("<" + snapshot.data.guild.name + ">"),
       Text(snapshot.data.guild.realm),
    }