【问题标题】:Mapping response.body to model class将 response.body 映射到模型类
【发布时间】:2021-07-27 21:01:35
【问题描述】:

我正在尝试将响应映射到模型类,然后一一显示所有元素,以便用户可以向下滚动。回复是这样的:

{"items":[{"id":"bd9acd37-5c91-47cb-a71e-0e43fb2f7882","imageUrl":"","title":"fak hez as","city":"Gdansk"},{"id":"210ad8c8-d279-4c38-845c-34c772cfec21","imageUrl":"","title":"Some random title :)","city":"Warsaw"}],"total":2,"pageNumber":1}

还有我用https://plugins.jetbrains.com/plugin/12562-jsontodart-json-to-dart-生成的模型

class Advertisement {
  List<Items>? _items;
  int? _total;
  int? _pageNumber;

  List<Items>? get items => _items;

  int? get total => _total;

  int? get pageNumber => _pageNumber;

  Advertisement({List<Items>? items, int? total, int? pageNumber}) {
    _items = items;
    _total = total;
    _pageNumber = pageNumber;
  }

  Advertisement.fromJson(dynamic json) {
    if (json["items"] != null) {
      _items = [];
      json["items"].forEach((v) {
        _items?.add(Items.fromJson(v));
      });
    }
    _total = json["total"];
    _pageNumber = json["pageNumber"];
  }

  Map<String, dynamic> toJson() {
    var map = <String, dynamic>{};
    if (_items != null) {
      map["items"] = _items?.map((v) => v.toJson()).toList();
    }
    map["total"] = _total;
    map["pageNumber"] = _pageNumber;
    return map;
  }
}

/// id : "bd9acd37-5c91-47cb-a71e-0e43fb2f7882"
/// imageUrl : ""
/// title : "fak hez as"
/// city : "Gdansk"

class Items {
  String? _id;
  String? _imageUrl;
  String? _title;
  String? _city;

  String? get id => _id;

  String? get imageUrl => _imageUrl;

  String? get title => _title;

  String? get city => _city;

  Items({String? id, String? imageUrl, String? title, String? city}) {
    _id = id;
    _imageUrl = imageUrl;
    _title = title;
    _city = city;
  }

  Items.fromJson(dynamic json) {
    _id = json["id"];
    _imageUrl = json["imageUrl"];
    _title = json["title"];
    _city = json["city"];
  }

  Map<String, dynamic> toJson() {
    var map = <String, dynamic>{};
    map["id"] = _id;
    map["imageUrl"] = _imageUrl;
    map["title"] = _title;
    map["city"] = _city;
    return map;
  }
}

我的屏幕:

import 'dart:convert';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:.../constants/AppConstants.dart';
import 'package:.../ui/pages/home/page/Advertisement.dart';
import 'package:.../util/HttpActions.dart';

import 'BottomAppBar.dart';
import 'FAB.dart';
import 'Advertisement.dart';

class HomePage extends StatefulWidget {
  final String jwt;

  const HomePage(this.jwt);

  @override
  _HomePage createState() => _HomePage();

  factory HomePage.fromBase64(String jwt) => HomePage(jwt);
}

class _HomePage extends State<HomePage> {
  late final String jwt;

  @override
  void initState() {
    super.initState();
    jwt = widget.jwt;
  }

  @override
  Widget build(BuildContext context) => Scaffold(
        body: Scaffold(
          backgroundColor: const Color(0xFEF9F9FC),
          floatingActionButtonLocation:
              FloatingActionButtonLocation.centerDocked,
          floatingActionButton: buildFAB(),
          bottomNavigationBar: BuildBottomAppBar(),
          body: Container(
            padding: EdgeInsets.all(35.0),
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            child: Column(
              children: [
                FutureBuilder(
                  future: fetchAdvertisements(),
                  builder: (context, snapshot) => snapshot.hasData
                      ? Text("")
                      : snapshot.hasError
                          ? Text("An error occurred")
                          : CircularProgressIndicator(),
                ),
              ],
            ),
          ),
        ),
      );

  Future<List<Advertisement>?> fetchAdvertisements() async {
    var response = await HttpActions.makeHttpGet(
        {},
        AppConstants.ADVERTISEMENTS_ENDPOINT,
        {HttpHeaders.contentTypeHeader: HttpActions.APPLICATION_JSON_HEADER});

    print(response.statusCode);
    if (response.statusCode == 200) {
      print(response.body);
      final responseList = json.decode(response.body);
      print(responseList);
      List<Advertisement> z = (json.decode(response.body) as List)
          .map((i) => Advertisement.fromJson(i))
          .toList();
      print(z);
      return null;
    } else {
      throw Exception('Failed to load post');
    }
  }
}

执行此行时发生错误:

List<Advertisement> z = (json.decode(response.body) as List)
              .map((i) => Advertisement.fromJson(i))
              .toList();

它没有映射到这个列表

调试时我得到:

我做错了什么?模型类有问题吗?

【问题讨论】:

    标签: json flutter dart decode


    【解决方案1】:

    您在代码中犯的另一个错误是,您在构建(BuildContext 上下文)中调用了 fetchAdvertisement() 方法。这意味着每次调用 build() 方法。它也会调用 fetchAdvertisement()。

     列(
                  孩子们: [
                    未来建造者(
                      未来:fetchAdvertisements(),
                      builder: (context, snapshot) => snapshot.hasData
                          ?文本(””)
                          : 快照.hasError
                              ? Text("发生错误")
                              :循环进度指示器(),
                    ),
                  ],
                ),
    

    为了避免这样的问题。

    后期函数_fetchAdvertisements; 无效初始化状态(){ super.initState(); _fetchAdvertisements = fetchAdvertisements(); } 柱子( 孩子们: [ 未来建造者( 未来:_fetchAdvertisements, builder: (context, snapshot) => snapshot.hasData ?文本(””) : 快照.hasError ? Text("发生错误") :循环进度指示器(), ), ], ),

    【讨论】:

    • 参数类型'Function'不能分配给参数类型'Future?'。
    • 函数? _fetchAdvertisements;
    • 你能提供完整的答案吗?它不起作用。
    • 检查我的完整代码示例,这将解决您的问题。 :) 。如果这解决了你的问题。请告诉我。
    • 我说的是在构建(BuildContext 上下文)中调用 fetchAdvertisement() 方法。此答案中的此代码示例不起作用。什么是函数? _fetchAdvertisements;我不能这样声明。
    【解决方案2】:

    你不能简单地用 cast as List 解析它。因为您的响应甚至不是列表。

    {
      "items": [
        {
          "id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882",
          "imageUrl": "",
          "title": "fak hez as",
          "city": "Gdansk"
        },
        {
          "id": "210ad8c8-d279-4c38-845c-34c772cfec21",
          "imageUrl": "",
          "title": "Pozdrawiam z Łodzi :)",
          "city": "Warsaw"
        }
      ],
      "total": 2,
      "pageNumber": 1
    }
    

    对于这个响应,你可以这样解析:

    Advertisement.fromJson(json.decode(response.body))
    

    但现在你只有Advertisement 的一项。

    如果您的回复是这样的,带有多个广告:

    {
      "advertisements": [
        {
          "items": [
            {
              "id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882",
              "imageUrl": "",
              "title": "fak hez as",
              "city": "Gdansk"
            },
            {
              "id": "212ad8c8-d279-4c38-845c-34c772cfec21",
              "imageUrl": "",
              "title": "Great city!",
              "city": "Łódź"
            }
          ],
          "total": 2,
          "pageNumber": 1
        },
        {
          "items": [
            {
              "id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882",
              "imageUrl": "",
              "title": "fak hez as",
              "city": "Gdansk"
            },
            {
              "id": "210ad8c8-d279-4c38-845c-34c772cfec21",
              "imageUrl": "",
              "title": "Some random title :)",
              "city": "Warsaw"
            }
          ],
          "total": 2,
          "pageNumber": 1
        }
      ]
    }
    

    您可以使用以下代码简单地解析它:

    List<Advertisement> advertisements = [
          for (final advertisement in json.decode(response2)['advertisements'])
            Advertisement.fromJson(advertisement)
        ];
    

    您可以使用JsonSerializable 学习如何正确进行 JSON 序列化,我建议您阅读此here

    【讨论】:

      【解决方案3】:

      我刚刚复制了您的 respond.body 文本并向您展示了一个虚拟示例。一切都将以相同的方式完成,天气您使用 HTTP 调用。始终确保您知道会发生什么反应。

       class __AppState extends State<_App> {
            @override
            void initState() {
              // TODO: implement initState
              super.initState();
              convertApiResponse();
            }
          
            Future<String> getApiJson() async {
              return '{"items":[{"id":"bd9acd37-5c91-47cb-a71e-0e43fb2f7882","imageUrl":"","title":"fak hez as","city":"Gdansk"},{"id":"210ad8c8-d279-4c38-845c-34c772cfec21","imageUrl":"","title":"Some random title :)","city":"Warsaw"}],"total":2,"pageNumber":1} ';
            }
          
            Future<void> convertApiResponse() async {
              final data = await getApiJson();
              final decodedData = json.decode(data) as Map;
              Advertisement x = Advertisement.fromJson(decodedData);
              x._items!.forEach((element) {
                log("Item-> City: ${element.city}");
                log("Item->ID: ${element.id}");
                log("Item->ImageURL: ${element.imageUrl}");
                log("Item->Title: ${element.title}");
              });
              log("Page Number: ${x.pageNumber}");
              log("Total: ${x.total}");
            }
          
            @override
            Widget build(BuildContext context) {
              return MaterialApp(home: Scaffold());
            }
          }
      

      Untouched Items.dart

      class Items {
        String? _id;
        String? _imageUrl;
        String? _title;
        String? _city;
      
        String? get id => _id;
      
        String? get imageUrl => _imageUrl;
      
        String? get title => _title;
      
        String? get city => _city;
      
        Items({String? id, String? imageUrl, String? title, String? city}) {
          _id = id;
          _imageUrl = imageUrl;
          _title = title;
          _city = city;
        }
      
        Items.fromJson(dynamic json) {
          _id = json["id"];
          _imageUrl = json["imageUrl"];
          _title = json["title"];
          _city = json["city"];
        }
      
        Map<String, dynamic> toJson() {
          var map = <String, dynamic>{};
          map["id"] = _id;
          map["imageUrl"] = _imageUrl;
          map["title"] = _title;
          map["city"] = _city;
          return map;
        }
      }
      

      Untouched Advertisement.dart

      class Advertisement {
        List<Items>? _items;
        int? _total;
        int? _pageNumber;
      
        List<Items>? get items => _items;
      
        int? get total => _total;
      
        int? get pageNumber => _pageNumber;
      
        Advertisement({List<Items>? items, int? total, int? pageNumber}) {
          _items = items;
          _total = total;
          _pageNumber = pageNumber;
        }
      
        Advertisement.fromJson(dynamic json) {
          if (json["items"] != null) {
            _items = [];
            json["items"].forEach((v) {
              _items?.add(Items.fromJson(v));
            });
          }
          _total = json["total"];
          _pageNumber = json["pageNumber"];
        }
      
        Map<String, dynamic> toJson() {
          var map = <String, dynamic>{};
          if (_items != null) {
            map["items"] = _items?.map((v) => v.toJson()).toList();
          }
          map["total"] = _total;
          map["pageNumber"] = _pageNumber;
          return map;
        }
      }
      

      【讨论】:

        【解决方案4】:

        这是一张解决您在每次构建时调用 fetchAdvertisements() 的图片

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-05
          • 1970-01-01
          • 2018-06-19
          • 1970-01-01
          • 2020-05-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多