Не является подтипом типа ‘(String, dynamic) => MapEntry’ из ‘transform’)

#json #flutter #dart

#json #флаттер #dart

Вопрос:

Я извлекаю некоторые продукты с сервера, но получаю сообщение об ошибке, поскольку было вызвано другое исключение: неправильное использование ParentDataWidget . AsyncSnapshot<Список>(ConnectionState.waiting, null, тип ‘(динамический) => ProductsModel’ не является подтипом типа ‘(String, dynamic) => MapEntry<динамический, динамический>’ из ‘transform’)

 Incorrect use of ParentDataWidget.
The ParentDataWidget Flexible(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData.

Usually, this means that the Flexible widget has the wrong ancestor RenderObjectWidget. Typically, Flexible widgets are placed directly inside Flex widgets.
The offending Flexible is currently placed inside a RepaintBoundary widget.

The ownership chain for the RenderObject that received the incompatible parent data was:
  RichText ← Text ← FutureBuilder<List<ProductsModel>> ← Container ← Flexible ← RepaintBoundary ← IndexedSemantics ← NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← ⋯
When the exception was thrown, this was the stack: 
#0      RenderObjectElement._updateParentData.<anonymous closure> (package:flutter/src/widgets/framework.dart:5689:11)
#1      RenderObjectElement._updateParentData (package:flutter/src/widgets/framework.dart:5705:6)
#2      ParentDataElement._applyParentData.applyParentDataToChild (package:flutter/src/widgets/framework.dart:4939:15)
#3      ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:4600:14)
#4      ParentDataElement._applyParentData.applyParentDataToChild (package:flutter/src/widgets/framework.dart:4942:15)
...
Another exception was thrown: Incorrect use of ParentDataWidget.
AsyncSnapshot<List<ProductsModel>>(ConnectionState.waiting, null, type '(dynamic) => ProductsModel' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform')
  

И это мой класс ProductModel

 class ProductsModel {
  String adid;
  String adsubcatid;
  String aduserid;
  String adname;
  String adcoverimg;
  String addesc;
  String adsPrice;
  String adsLocation;
  String createdDate;
  String userName;
  String images;

  ProductsModel(
      {this.adid,
        this.adsubcatid,
        this.aduserid,
        this.adname,
        this.adcoverimg,
        this.addesc,
        this.adsPrice,
        this.adsLocation,
        this.createdDate,
        this.userName,
        this.images});

  factory ProductsModel.fromJson(Map<String, dynamic> json) {
    return ProductsModel(
      adid: json['adid'],
      adsubcatid: json['adsubcatid'],
      aduserid: json['aduserid'],
      adname: json['adname'],
      adcoverimg: json['adcoverimg'],
      addesc: json['addesc'],
      adsPrice: json['ads_price'],
      adsLocation: json['ads_location'],
      createdDate: json['created_date'],
      userName: json['user_name'],
      images: json['images']
    );
  }
}
  

И это главная страница

 @override
  void initState() {
    getProducts();
    super.initState();
  }

@override
  Widget build(BuildContext context) {
    print("Home");
    return Scaffold(
      appBar: AppBar(
        leading: Image.asset('assets/images/ic_logo.png'),
        actions: <Widget>[
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: FlatButton.icon(
              onPressed: () {},
              icon: Icon(Icons.location_on),
              label: Text('Mysuru, India'),
              textColor: Colors.white,
            ),
          ),
        ],
      ),
      body: CustomScrollView(
        slivers: [
          SliverToBoxAdapter(
            child: SizedBox(
              child: _search(),
            ),
          ),
          SliverToBoxAdapter(
            child: SizedBox(
              child: HorizontalCategories(),
            ),
          ),
          SliverGrid(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              childAspectRatio: 0.7,
            ),
            delegate: SliverChildBuilderDelegate(
                (context, index) => _products(context)),
          )
        ],
      ),
    );
  }

 Widget _products(BuildContext context) {
    print("Inside products");
    return Flexible(
      child: Container(
        child: FutureBuilder<List<ProductsModel>>(
          future: _fetchProducts(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              print("Has data");
              List<ProductsModel> data = snapshot.data;
              return _productsList(data);
            } else if (snapshot.hasError) {
              print("Error");
              print(snapshot.hasError);
              print(snapshot);
              return Text('${snapshot.hasError}');
            } else {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
          },
        ),
      ),
    );
  }

  Future<List<ProductsModel>> _fetchProducts() async {
    String productsUrl = Constant.productsUrl;
    Map<String, String> headers = {'Content-Type': 'application/json'};

    final response = await http.get(productsUrl, headers: headers);
    if (response.statusCode == 200) {
      var jsonResponse = json.decode(response.body);
      print(jsonResponse);
      return jsonResponse
          .map((products) => new ProductsModel.fromJson(products))
          .toList();
    } else {
      throw Exception('Failed to load Categories from API');
    }
  }

  

И это JsonResponse

 {
    "status": true,
    "record": [
        {
            "adid": "1",
            "adsubcatid": "1",
            "aduserid": "2",
            "adname": "Ads",
            "adcoverimg": "Royal Enfield Classic 350 Images Classic 350 Photos amp; 360 View_files.JPG",
            "addesc": "vsv dsv  sd fds fd fdsf dsf s fds fdssfdf c sfdf sd",
            "ads_price": "3000",
            "ads_location": "mysore",
            "created_date": "06/10/2020",
            "user_name": "sunil",
            "images": "{'adsimg_img':'2.JPG'},{'adsimg_img':'3.JPG'},{'adsimg_img':'4.JPG'}"
        }
    ]
}
  

Комментарии:

1. Не могли бы вы добавить, пожалуйста jsonResponse ? Пример ответа.

2. jsonResponse не является итерируемым (списком), поэтому map его нельзя вызвать.

3. Гибкие виджеты могут иметь только гибкие виджеты (строка или столбец) в качестве родителей. Попробуйте удалить гибкий виджет в методе _products .

4. Даже если я удаляю гибкий, он выдает ошибку в Futurebuilder

Ответ №1:

Функция Map не может быть применена к JsonResponse .

 return jsonResponse
          .map((products) => new ProductsModel.fromJson(products))
          .toList();
  

JsonResponse содержит записи в record поле, которые должны быть сопоставлены ProductsModel .

 return jsonResponse
          .record
          .map((products) => new ProductsModel.fromJson(products))
          .toList();
  

Ответ №2:

вы хотите получить список record , на который вы должны ориентироваться!

 var data = jsonResponse['record'];
  

Полный вызов api

   Future<List<ProductsModel>> _fetchProducts() async {
    String productsUrl = Constant.productsUrl;
    Map<String, String> headers = {'Content-Type': 'application/json'};

    final response = await http.get(productsUrl, headers: headers);
    if (response.statusCode == 200) {
      var jsonResponse = json.decode(response.body);
      var data = jsonResponse['record'];
      return data
          .map((products) => new ProductsModel.fromJson(products))
          .toList();
    } else {
      throw Exception('Failed to load Categories from API');
    }
  }
  

Ответ №3:

Корень вашего «JsonResponse» не является списком.

Попробуйте что-то вроде этого:

 var jsonResponse = json.decode(response.body);
var objRoot = ObjRoot.fromJson(jsonResponse);
var products = objRoot.record.map((obj) => ProductsModel.fromJson(obj)).toList();
return products;