【问题标题】:How to check for NULL when mapping nested JSON?映射嵌套 JSON 时如何检查 NULL?
【发布时间】:2019-05-26 11:47:46
【问题描述】:

我正在尝试将嵌套的 JSON 映射到模型对象,问题是当它返回 null 时,它会破坏所有代码,我想检查 null 是否做某事但不破坏应用程序。

JSON 文件:

[
    {
        "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",
                    }
                    ]
}
]

映射到对象的代码:

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

在 null 上调用了方法“map”。 Receiver: null [0] 有时返回 null ;

【问题讨论】:

    标签: json dart flutter


    【解决方案1】:

    这是一个简单的解决方案:

    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;
    }
    

    使用:

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

    该函数使用keys 中提供的键对map 进行递归迭代,如果缺少某个键,它将返回null,否则它将返回最后一个键的值。

    【讨论】:

    • 喜欢这种方法。正是我想要的。我只是想从嵌套的 json 中获取价值,但我不想序列化并从中创建类。这是完美的解决方案。
    • 但是在使用像 0 这样的索引时会出错。我收到此错误“type 'List' is not a subtype of type 'Map'”。有什么解决办法吗?
    【解决方案2】:

    根据我的评论,我建议您使用代码生成库将JSON 解析为JSON Models

    阅读this article,了解如何使用(例如)json_serializable 包。

    此类库承担了生成所有样板代码的所有繁琐工作来创建您的模型类,并且它们将 null 值视为强制性或非强制性的。

    例如,如果您这样注释类 Person:

    @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);
    }
    

    使用 (nullable: true) 模型的 dart 类将跳过空值字段。

    更新

    因为我渴望技术,所以我给了quicktype 工具(由 Christoph Lachenicht 建议)尝试使用您的示例。

    我准备了一个 mock api 和一个文件 example.json,提供您发布的 JSON。我只取了一个元素,而不是数组。您可以在这里查看example.json

    安装 QuickType 后,我为这个 json 生成了模型类:

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

    请注意这里的 cli 参数 --all-properties-optional,它会为缺失的字段创建空检查。

    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(),
    };
    

    然后我在example.dart中使用了Example类

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

    一切顺利。

    注意 当然,当你使用这个类时,你必须在使用它们之前检查它的字段是否为空:

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

    就是这样。我希望能把你引向正确的方向。

    【讨论】:

    • 似乎所有样板都可以简化为"content" : content?.toJson(),。我想知道他们为什么要这样做。
    • @RandalSchwartz 实际上我已经意识到我已经发布了生成类的序列化代码,而不是反序列化部分^_^。顺便说一句,对于序列化部分,在调用 toJson 之前检查内容似乎没问题。无论如何,我没有深入到生成的类中。我的意思是只使用一个代码生成库(你喜欢的那个)而不是手动映射 json。
    猜你喜欢
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多