Search code examples
flutterdartflutter-listviewdart-null-safetynull-check

Null check operator used on null value when I have defined a model the particular list using null safety in flutter


I want to check if list is empty then show some image and if it is not I want to show the contents of the list but I am getting an error when checking if the list is empty.This is my model class

import 'dart:convert';

class ProductModel {
  ProductModel({
    this.name,
    this.description,
    this.sellerId,
    this.published,
    this.origin,
    this.weight,
    this.material,
    this.photoUrl,
    this.discount,
    this.price,
    this.quantity,
    this.sizes
  });

  String? name;
  String? description;
  String? sellerId;
  String? published;
  String? origin;
  String? weight;
  String? material;
  List<String>? photoUrl=[];
  int? discount;
  List<String>? sizes=[];
  List<String>? quantity=[];
  List<String>? price=[];

  factory ProductModel.fromRawJson(String str) => ProductModel.fromJson(json.decode(str));

  String toRawJson() => json.encode(toJson());

  factory ProductModel.fromJson(Map<String, dynamic> json) => ProductModel(
    name: json["name"] == null ? null : json["name"],
    description: json["description"] == null ? null : json["description"],
    sellerId: json["sellerId"] == null ? null : json["sellerId"],
    published: json["published"] == null ? null : json["published"],
    origin: json["origin"] == null ? null : json["origin"],
    weight: json["weight"] == null ? null : json["weight"],
    material: json["material"] == null ? null : json["material"],
    photoUrl: json["photoUrl"] == null ? null : List<String>.from(json["photoUrl"].map((x) => x)),
    discount: json["discount"] == null ? null : json["discount"],
    sizes: json["sizes"] == null ? null : List<String>.from(json["sizes"].map((x) => x)),
    price: json["price"] == null ? null : List<String>.from(json["price"].map((x) => x)),
    quantity: json["quantity"] == null ? null : List<String>.from(json["quantity"].map((x) => x)),
  );

  Map<String, dynamic> toJson() => {
    "name": name == null ? null : name,
    "description": description == null ? null : description,
    "sellerId": sellerId == null ? null : sellerId,
    "published": published == null ? null : published,
    "origin": origin == null ? null : origin,
    "weight": weight == null ? null : weight,
    "material": material == null ? null : material,
    "photoUrl": photoUrl == null ? null : List<String>.from(photoUrl!.map((x) => x)),
    "discount": discount == null ? null : discount,
    "sizes": sizes == null ? null : List<dynamic>.from(sizes!.map((x) => x)),
    "price": price == null ? null : List<dynamic>.from(price!.map((x) => x)),
    "quantity": quantity == null ? null : List<dynamic>.from(quantity!.map((x) => x)),
  };
}

But I am getting null check operator used on null value. Can someone please point out what's going wrong here. thanks

This is my code usage:

Padding(
              padding: const EdgeInsets.all(8.0),
              child: Container(
                decoration: BoxDecoration(
                    border: Border.all(
                      color: Colors.orange,
                    ),
                    borderRadius: BorderRadius.circular(20)),
                height: MediaQuery.of(context).size.height / 2.5,
                width: MediaQuery.of(context).size.width - 100,
                child: addProductCtrl.product.sizes!.length > 0
                    ? Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: GetBuilder<AddProductCtrl>(
                            id: editDetails,
                            builder: (_) {
                              return new ListView.builder(
                                  scrollDirection: Axis.vertical,
                                  itemCount: addProductCtrl.product.sizes!.length,
                                  itemBuilder: (_, index) => Row(
                                        mainAxisAlignment:
                                            MainAxisAlignment.spaceBetween,
                                        children: [
                                          Padding(
                                            padding:
                                                const EdgeInsets.all(8.0),
                                            child: Text(
                                                addProductCtrl.product.sizes![index],
                                                style: TextStyle(
                                                    fontSize: 25)),
                                          ),
                                          Padding(
                                            padding:
                                                const EdgeInsets.all(8.0),
                                            child: Text(
                                                "Rs.${addProductCtrl.product.price![index]}",
                                                style: TextStyle(
                                                    fontSize: 25)),
                                          ),
                                          Padding(
                                            padding:
                                                const EdgeInsets.all(8.0),
                                            child: Text(
                                                addProductCtrl.product.quantity![index],
                                                style: TextStyle(
                                                    fontSize: 25)),
                                          ),
                                        ],
                                      ));
                            }),
                      )
                    : Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Center(
                            child: Text("Add Details ",
                                style: TextStyle(fontSize: 25))),
                      ),
              ),
            ),

error pic


Solution

  • Based on the JSON example I have rewritten your JSON parser to the following which is also nullsafe:

    class ProductModel {
      ProductModel({
        required this.name,
        required this.description,
        required this.sellerId,
        required this.published,
        required this.origin,
        required this.weight,
        required this.material,
        required this.photoUrl,
        required this.discount,
        required this.price,
        required this.quantity,
        required this.sizes,
      });
    
      String name;
      String description;
      String sellerId;
      String published;
      String origin;
      String? weight;
      String? material;
      List<String> photoUrl;
      int? discount;
      List<String> sizes;
      List<String> price;
      List<String> quantity;
    
      factory ProductModel.fromRawJson(String str) =>
          ProductModel.fromJson(json.decode(str) as Map<String, dynamic>);
    
      String toRawJson() => json.encode(toJson());
    
      factory ProductModel.fromJson(Map<String, dynamic> json) => ProductModel(
            name: json["name"] as String,
            description: json["description"] as String,
            sellerId: json["sellerId"] as String,
            published: json["published"] as String,
            origin: json["origin"] as String,
            weight: json["weight"] as String?,
            material: json["material"] as String?,
            photoUrl: (json["photoUrl"] as List?)?.cast<String>().toList() ?? [],
            discount: json["discount"] as int?,
            sizes: (json["sizes"] as List?)?.cast<String>().toList() ?? [],
            price: (json["price"] as List?)?.cast<String>().toList() ?? [],
            quantity: (json["qty"] as List?)?.cast<String>().toList() ?? [],
          );
    
      Map<String, dynamic> toJson() => <String, dynamic>{
            "name": name,
            "description": description,
            "sellerId": sellerId,
            "published": published,
            "origin": origin,
            if (weight != null) "weight": weight,
            if (material != null) "material": material,
            if (photoUrl.isNotEmpty) "photoUrl": photoUrl,
            if (discount != null) "discount": discount,
            if (sizes.isNotEmpty) "sizes": sizes,
            if (price.isNotEmpty) "price": price,
            if (quantity.isNotEmpty) "qty": quantity,
          };
    }
    
    const jsonInput = '''{
      "name": "test",
      "description": "",
      "sellerId": "",
      "published": "",
      "origin": "",
      "weight": "",
      "material": "",
      "photoUrl": [],
      "discount": 10,
      "size": [],
      "price": [],
      "qty": []
    }
    ''';
    
    void main() {
      print(ProductModel.fromRawJson(jsonInput).toJson());
      // {name: test, description: , sellerId: , published: , origin: , weight: , material: , discount: 10}
    }
    

    I was not sure about how you wanted the toJson method to work but I have added some examples on how you can make the output so it does not contain the fields if they are e.g. empty lists.