ITADN

Unable to skip empty List when serializing JSON with JsonConverter

#1569OpenNoBrainer 创建于 2026-04-26
N
NoBrainercommented
### Context I got my desired behavior to work with `@JsonKey`, but I couldn't get it to work with a `JsonConverter`. (I think this should be a solution to a [related issue](https://github.com/google/json_serializable.dart/issues/1369), but it doesn't work as I expect.) Here is my source code: ```dart // my_model.dart import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; part 'my_model.g.dart'; @JsonSerializable( explicitToJson: true, converters: [ StringTrimConverter(), IgnoreEmptyListConverter(), IgnoreEmptyNullableListConverter(), ], includeIfNull: false, ) class MyModel extends Equatable { final List<int> intList; final List<String> strList; final String str; final String? strOptional; @JsonKey(toJson: listToJson) final List<int> intListWithJsonKey; const MyModel({ this.intList = const [], this.intListWithJsonKey = const [], this.strList = const [], this.str = '', this.strOptional = '', }); @override List<Object?> get props => [ intList, intListWithJsonKey, strList, str, strOptional, ]; factory MyModel.fromJson(Map<String, dynamic> json) => _$MyModelFromJson(json); Map<String, dynamic> toJson() => _$MyModelToJson(this); } List? listToJson(List list) => list.isEmpty ? null : list; /// Ensure Strings are trimmed when serialized and deserialized. class StringTrimConverter implements JsonConverter<String, String> { const StringTrimConverter(); @override String fromJson(String json) => json.trim(); @override String toJson(String str) => str.trim(); } /// Ensure list keys are skipped when serializing JSON class IgnoreEmptyListConverter implements JsonConverter<List, List?> { const IgnoreEmptyListConverter(); @override List fromJson(List? json) => json ?? []; @override List? toJson(List list) => list.isEmpty ? null : list; } /// Ensure list keys are skipped when serializing JSON class IgnoreEmptyNullableListConverter implements JsonConverter<List?, List?> { const IgnoreEmptyNullableListConverter(); @override List? fromJson(List? json) => json ?? []; @override List? toJson(List? list) => (list == null || list.isEmpty) ? null : list; } ``` And here is my generated code (after running `dart run build_runner build`): ```dart // my_model.g.dart // GENERATED CODE - DO NOT MODIFY BY HAND part of 'my_model.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** MyModel _$MyModelFromJson(Map<String, dynamic> json) => MyModel( intList: (json['intList'] as List<dynamic>?) ?.map((e) => (e as num).toInt()) .toList() ?? const [], intListWithJsonKey: (json['intListWithJsonKey'] as List<dynamic>?) ?.map((e) => (e as num).toInt()) .toList() ?? const [], strList: (json['strList'] as List<dynamic>?) ?.map((e) => const StringTrimConverter().fromJson(e as String)) .toList() ?? const [], str: json['str'] == null ? '' : const StringTrimConverter().fromJson(json['str'] as String), strOptional: _$JsonConverterFromJson<String, String>( json['strOptional'], const StringTrimConverter().fromJson, ) ?? '', ); Map<String, dynamic> _$MyModelToJson(MyModel instance) => <String, dynamic>{ 'intList': instance.intList, 'strList': instance.strList.map(const StringTrimConverter().toJson).toList(), 'str': const StringTrimConverter().toJson(instance.str), 'strOptional': ?_$JsonConverterToJson<String, String>( instance.strOptional, const StringTrimConverter().toJson, ), 'intListWithJsonKey': ?listToJson(instance.intListWithJsonKey), }; Value? _$JsonConverterFromJson<Json, Value>( Object? json, Value? Function(Json json) fromJson, ) => json == null ? null : fromJson(json as Json); Json? _$JsonConverterToJson<Json, Value>( Value? value, Json? Function(Value value) toJson, ) => value == null ? null : toJson(value); ``` ### The Good - `StringTrimConverter` works on a `String`. - `StringTrimConverter` works on a `List<String>`. - `includeIfNull: false` works on a `String?`. - `@JsonKey(toJson: listToJson)` works on an individual `List` field. - Note: This is the behavior I want with a `JsonConverter`. ### The Problem - `IgnoreEmptyListConverter` is not used at all. - `IgnoreEmptyNullableListConverter` is not used at all. 1. How do I do make this use one of the unused converters? (In other words, how do I do what I'm doing with `@JsonKey` without having to put `@JsonKey` on every `List` field?) 2. Is there something I need to change with one of the converters to make it work?
0 条评论