google/built_value.dart

[Quesion] can a type have multiple serializeres?

Closed this issue · 5 comments

I have the normal case when the server and client have different requirements.
The client needs this:

  int get id;
  String get name;
  T? get object;

But when I serialize to push info to the server, it only needs the id, so I created a customer Serializer with this:

  @override
  int serialize(Serializers serializers, Many2one object,
      {FullType specifiedType = FullType.unspecified}) {
    return object.id;
  }

Until now, it worked fine for me.
But I need to also persist the client object to local storage. So I serialize it, convert it to a json string, and save the string in SharedPreferences, with this:

  Future persistOrder() async {
    final prefs = await SharedPreferences.getInstance();
    var orderString = currentOrder.value?.toJson() ?? '';
    if (orderString.isNotEmpty) {
      await prefs.setString('currentOrder', orderString);
    }
  }

The toJson method above is here:

  String toJson() {
    var map = serializers.serialize(this) as Map;
    map.removeWhere((key, value) => key == r'$');
    return json.encode(map);
  }

The problem is that, when I serialize to save in SharedPreferences, I want the serializer to behave differently, and instead of using the custom serializer that I defined, I want it to use an auto generated serialzier that will save all data. Why? because when I load the Order data from SharedPreferences, I need to accesss all the data.

Maybe I should approach this differently and solve it another way, but if having multiple serializes is a good thing, is it possible?

If I understood correctly: you can have a different Serializers instance with a different serializer installed for that type.

Call toBuilder on a Serializers, then add to add a new serializer, if one is already installed then it gets overridden.

Does that do what you want? :)

@davidmorgan thanks, this solved my issue, never though of doing it this way.

Serializers code:

final Serializers serializers = (_$serializers.toBuilder()
      ..addPlugin(StandardJsonPlugin())
      ..addPlugin(OdooStringSerializerPlugin(fullType: const FullType(String)))
    )
    .build();

final Serializers serverSerializers = (_$serializers.toBuilder()  // added this
      ..addPlugin(StandardJsonPlugin())
      ..addPlugin(OdooStringSerializerPlugin(fullType: const FullType(String)))
      ..add(Many2oneSerializer()))  // added the cusotm serializer here
    .build();

I don't like the fact that I repeated some parts here (I am still new to dart) but it works.

Looks good!

I think instead of repeating addPlugin you could start with serializers.toBuilder which will already have the plugins :)

So the serializer itself uses the builder pattern!
A better code would be:

final Serializers serializers = (_$serializers.toBuilder()
      ..addPlugin(StandardJsonPlugin())
      ..addPlugin(OdooStringSerializerPlugin(fullType: const FullType(String))))
    .build();

final Serializers serverSerializers = (serializers.toBuilder()
      ..add(Many2oneSerializer()))
    .build();

Of course, it's builders all the way down ;) ...

Looks good to me. Thanks :)