Unable to skip empty List when serializing JSON with JsonConverter
### 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 条评论