Home > OS >  Flutter/Dart: Reduce size of JSON file
Flutter/Dart: Reduce size of JSON file

Time:12-18

I have a a few classes that i serialize nicely with the flutter jsonEncode/jsonDecode macros:

    part 'friend.g.dart';


@JsonSerializable(explicitToJson: true)
class Friend {
  Friend({required this.name});

  @JsonKey(required: true)
  late String name;

  @JsonKey(required: true)
  late final Preferences prefTree;

  @JsonKey(required: false, defaultValue: "assets/avatars/cat.png")
  late String avatarAsset = avatarAssets[Random().nextInt(avatarAssets.length-1)];


  factory Friend.fromJson(Map<String, dynamic> json) => _$FriendFromJson(json);
  Map<String, dynamic> toJson() => _$FriendToJson(this);
  Map<String, dynamic> _$FriendToJson(Friend instance) => <String, dynamic>{
    'name': instance.name,
    'avatarAsset': instance.avatarAsset,
    'isFavorite': instance.isFavorite,
    'prefTree': instance.prefTree,
  };
....
}

It works very finely, and when deserializing it will use the default values if the JSON value is not present in the json file.

The problem is the serializer.

What i would like is that

  1. when my class attribute has a default value, and
  2. the attribute is not required, and
  3. the value of the attribute of my instance is the same as the default value,

==> then the serializer would not write down the value in the json file. This would save me dozens of thousands of lines in the JSON file.

I read about the different JSON members, like "required", "defaultValue", etc, and i use them, but still the serializer does not seem to take this into account. Again, the deserializer works like a charm. So instead of having my classes serialized to this:

{
  "itemName": "Brown",
  "itemIconString": "",
  "isAPreference": false
},

I'd like to have it serialized like this (because of the default values):

   {
      "itemName": "Brown",
    },

Is it me or it is not possible to avoid the default value of a member to be outputed in the jsonEncode?

Thanks!

CodePudding user response:

I don't think JsonSerializable provides such an option. but you can write this manually.

here is an example:

class Test {
 
  final int a; // default is 1
  final int b; // default is 2
  
  Test({ this.a = 1, this.b = 2});
  
  Map<String, dynamic> toJson() {
    final result = <String, dynamic>{};
    if (a != 1) {
      result['a'] = a;
    }
    if (b != 2) {
      result['b'] = b;
    }
    return result;
  }
}


void main() {
  final t = Test(a: 1, b: 1);
  print(t.toJson());
}
  • Related