Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check for NULL when mapping nested JSON?

Tags:

json

flutter

dart

I'm trying to map a nested JSON to the model object, the problem is when it returns null, it will break all the code, I want to check if null do something but not break the app.

THE JSON FILE:

[
    {
        "id": 53,
        "date": "2018-12-28T08:51:11",
        "title": {
            "rendered": "this is for featured"
        },
        "content": {
            "rendered": "\n<p><g class=\"gr_ gr_3 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling\" id=\"3\" data-gr-id=\"3\">sdafkj</g> <g class=\"gr_ gr_10 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"10\" data-gr-id=\"10\">kj</g> <g class=\"gr_ gr_16 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"16\" data-gr-id=\"16\">asd</g> <g class=\"gr_ gr_18 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling\" id=\"18\" data-gr-id=\"18\">kadjsfk</g> kljadfklj sd</p>\n",
            "protected": false
        },
        "excerpt": {
            "rendered": "<p>sdafkj kj asd kadjsfk kljadfklj sd</p>\n",
            "protected": false
        },
        "author": 1,
        "featured_media": 54,
        "_links": {
            "self": [
                {
                    "href": "https://client.kurd.app/wp-json/wp/v2/posts/53"
                }
            ],

        },
        "_embedded": {
            "author": [
                {
                    "id": 1,
                    "name": "hooshyar",

                }
            ],
            "wp:featuredmedia": [
                {
                    "id": 54,

                    "source_url": "https://client.kurd.app/wp-content/uploads/2018/12/icannotknow_22_12_2018_18_48_11_430.jpg",
                    }
                    ]
}
]

CODE FOR MAPPING TO OBJECT:

  featuredMediaUrl = map ["_embedded"]["wp:featuredmedia"][0]["source_url"];

The method 'map' was called on null. Receiver: null [0] which sometimes returns null ;

like image 881
Hooshyar Avatar asked Dec 28 '18 17:12

Hooshyar


2 Answers

Here is a simple solution:

safeMapSearch(Map map, List keys) {
  if (map[keys[0]] != null) {
    if (keys.length == 1) {
      return map[keys[0]];
    }
    List tmpList = List.from(keys);
    tmpList.removeAt(0);
    return safeMapSearch(map[keys[0]], tmpList);
  }
  return null;
}

use:

featuredMediaUrl = safeMapSearch(map, ["_embedded","wp:featuredmedia",0,"source_url"]);

The function iterates recursively on the map with the keys supplied in keys, if a key is missing it will return null otherwise it will return the value of the last key.

like image 198
Elia Weiss Avatar answered Sep 27 '22 23:09

Elia Weiss


Following my comment I suggest you to use a code generation library to parse JSON to JSON Models.

Read this article that explain you how to use (for example) the json_serializable package.

Such libraries takes all the dirty job of generate all the boilerplate code to create your Model classes and they take care of null values as mandatory or not.

For example if you annotate a class Person like that:

@JsonSerializable(nullable: true)
class Person {
  final String firstName;
  final String lastName;
  final DateTime dateOfBirth;
  Person({this.firstName, this.lastName, this.dateOfBirth});
  factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
  Map<String, dynamic> toJson() => _$PersonToJson(this);
}

with (nullable: true) the dart class of your model will skip the null value fields.

enter image description here

UPDATE

Because I'm eager of technology I've given quicktype tool (suggested by Christoph Lachenicht) a try with your example.

I've prepared a mock api and a file example.json providing the JSON you've posted. I've taken only one element, not the array. And you can have a look here example.json.

After installin QuickType I've generate the model class for this json:

quicktype --lang dart --all-properties-optional example.json -o example.dart

Pay attention here to tha cli parameter --all-properties-optional that create null checks for missing fields.

Map<String, dynamic> toJson() => {
    "id": id == null ? null : id,
    "date": date == null ? null : date,
    "title": title == null ? null : title.toJson(),
    "content": content == null ? null : content.toJson(),
    "excerpt": excerpt == null ? null : excerpt.toJson(),
    "author": author == null ? null : author,
    "featured_media": featuredMedia == null ? null : featuredMedia,
    "_links": links == null ? null : links.toJson(),
    "_embedded": embedded == null ? null : embedded.toJson(),
};

Then I've used the Example class in example.dart

var jsonExampleResponse =
    await http.get('https://www.shadowsheep.it/so/53962129/testjson.php');
print(jsonExampleResponse.body);

var exampleClass = exampleFromJson(jsonExampleResponse.body);
print(exampleClass.toJson());

And all went fine.

N.B. Of course when you use this class you have to check if its fields are empty before using them:

print(exampleClass.embedded?.wpFeaturedmedia?.toString());

That's all. I hope to have put you in the rigth direction.

like image 35
shadowsheep Avatar answered Sep 27 '22 23:09

shadowsheep