Search code examples
flutterdartjson-serializable

Flutter json_serializable: fromJson returns null


the json I receive from the api looks like this:

{
  "USD": [
    {
      "name": "something",
      "value": 123
    },
    {
      "name": "something else",
      "value": 1234
    }
  ],
  "EUR": [
    ... same here
  ]
}

and my dart model looks like:

@JsonSerializable(anyMap: true, includeIfNull: true)
class StatisticsDto {
  StatisticsDto({this.statistics});

  final Map<String, List<StatisticsDetailDto>> statistics;

  factory StatisticsDto.fromJson(Map<String, dynamic> json) =>
      _$StatisticsDtoFromJson(json);

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

@JsonSerializable()
class StatisticsDetailDto {
  StatisticsDetailDto({
    this.name,
    this.value,
  });

  final String name;
  final num value;

  factory StatisticsDetailDto.fromJson(Map<String, dynamic> json) =>
      _$StatisticsDetailDtoFromJson(json);

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

I don't seem to be able to make it work, I get a 200 from the api, but the serialization returns null.

What am I doing wrong here?


Solution

  • This is what your JSON objects should look like converted to Dart data class with json_serializable

    {
        "USD": [{
                "name": "something",
                "value": 123
            },
            {
                "name": "something else",
                "value": 1234
            }
        ],
        "EUR": [{
                "name": "something",
                "value": 123
            },
            {
                "name": "something else",
                "value": 1234
            }
        ]
    }
    

    Dart data class with json_serializable without Map support:

    import 'package:json_annotation/json_annotation.dart';
    
    part 'statistic_dto.g.dart';
    part 'currency.g.dart';
    
    @JsonSerializable()
    class StatisticDto {
      StatisticDto({this.usd, this.eur});
    
      @JsonKey(name: 'USD')
      List<Currency>? usd;
      @JsonKey(name: 'EUR')
      List<Currency>? eur;
    
      factory StatisticDto.fromJson(Map<String, dynamic> json) {
        return _$StatisticDtoFromJson(json);
      }
    
      Map<String, dynamic> toJson() => _$StatisticDtoToJson(this);
    }
    
    @JsonSerializable()
    class Currency {
      Currency({this.name, this.value});
    
      String? name;
      int? value;
    
      factory Currency.fromJson(Map<String, dynamic> json) => _$CurrencyFromJson(json);
    
      Map<String, dynamic> toJson() => _$CurrencyToJson(this);
    }
    

    Run:

    flutter pub run build_runner build --delete-conflicting-outputs
    

    In your first example, your Map statistics have no key that why it always returns null. JSON file would look like this for your first class Data

    // For: final Map<String, Map<String, dynamic>> statistics;
    {
        "statistics": {
            "USD": {
                "name": "One",
                "value": 1
            },
            "EUR": {
                "name": "Four",
                "value": 4
            }
        }
    }