将 response.body 映射到模型类

问题描述

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

{"items":[{"id":"bd9acd37-5c91-47cb-a71e-0e43fb2f7882","imageUrl":"","title":"fak hez as","city":"Gdansk"},{"id":"210ad8c8-d279-4c38-845c-34c772cfec21","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>{};
    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();

它没有映射到这个列表

在调试时我得到:

result of executing of above method

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

解决方法

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

 Column(
              children: [
                FutureBuilder(
                  future: fetchAdvertisements(),builder: (context,snapshot) => snapshot.hasData
                      ? Text("")
                      : snapshot.hasError
                          ? Text("An error occurred")
                          : CircularProgressIndicator(),),],

为了避免这样的问题。

   
    late Function _fetchAdvertisements;

    void initState() {
        super.initState();
_fetchAdvertisements = fetchAdvertisements(); } 
       Column(
              children: [
                FutureBuilder(
                  future: _fetchAdvertisements,
,

您不能简单地使用强制转换 as List 来解析它。因为您的回复甚至不是列表。

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

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

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

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

,

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

enter image description here

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

未触及的物品.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;
  }
}

未触及的广告.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>{};
    if (_items != null) {
      map["items"] = _items?.map((v) => v.toJson()).toList();
    }
    map["total"] = _total;
    map["pageNumber"] = _pageNumber;
    return map;
  }
}
,

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

enter image description here