jsonflutterdartjson-serializable

Transforming empty nested map to object exception


I'm using json_serializable to parse complex JSON object to my model. Everything works fine except cases when I get empty object instead of Map<String,String>(second object in example)

[
  {
    "id": 123,
    "ColorPairs": {
      "MAA172M": "BLACK"
    },
    "Client": {
      "ClientId": "123",
      "ClientFullName": "TEST, TEST"
    }
  },
  {
    "id": 321,
    "ColorPairs": {},//EXCEPTION
    "Client": {
      "ClientId": "321",
      "ClientFullName": "TEST2, TEST2"
    }
  }
]

My model:

@JsonSerializable(explicitToJson: true)
class Delivery {
  Delivery(
    this.id,
    this.colorPairs,
    this.client,
  
  );

  @JsonKey(name: 'Id')
  int id;
  @JsonKey(name: 'ColorPairs')
  Map<String, String>? colorPairs;
  @JsonKey(name: 'Client')
  Client client;
 
  factory Delivery.fromJson(Map<String, dynamic> json) =>
      _$DeliveryFromJson(json);

  Map<String, dynamic> toJson() => _$DeliveryToJson(this);
}

And when it comes to parse empty map in second object I get:

Unhandled Exception: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>?' in type cast

What is the best way to handle cases of empty objects? Thank you in advance.


Solution

  • You can use custom fromJson with JsonKey

    @JsonSerializable(explicitToJson: true)
    class Delivery {
      Delivery(
        this.id,
        this.colorPairs,
        this.client,
      
      );
    
      @JsonKey(name: 'Id')
      int id;
      @JsonKey(name: 'ColorPairs', fromJson: toStringMap)//Here
      Map<String, String>? colorPairs;
      @JsonKey(name: 'Client')
      Client client;
     
      factory Delivery.fromJson(Map<String, dynamic> json) =>
          _$DeliveryFromJson(json);
    
      Map<String, dynamic> toJson() => _$DeliveryToJson(this);
    }
    
    //Map<dynamic, dynamic> to Map<String, String>
    Map<String, String>? toStringMap(Map? data) {
      return data?.map((dynamic key, dynamic value) => MapEntry(key.toString(), value.toString()));
    }