Json_serializable.dart: Getter with static value is not being serialized

Created on 1 Jun 2019  Â·  12Comments  Â·  Source: google/json_serializable.dart

$ flutter --version
Flutter 1.5.4-hotfix.2 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7a4c33425d (5 weeks ago) • 2019-04-29 11:05:24 -0700
Engine • revision 52c7a1e849
Tools • Dart 2.3.0 (build 2.3.0-dev.0.5 a1668566e5)

I have a bunch of the models that look like this:

class SomeModel implements GeneralModel
{
  SomeModel();

  factory AuthorizationStateWaitTdlibParameters.fromJSON(String json) =>
  _$AuthorizationStateWaitTdlibParametersFromJson(jsonDecode(json));

  @override
  String toJSON() => jsonEncode(_$AuthorizationStateWaitTdlibParametersToJson(this));

  @JsonKey(name: "CONSTRUCTOR")
  @override
  int get typeID => 42; // each model has its own constant
}

When I run flutter pub run build_runner build, typeID getter is not being serialized, though I need it to be:

Map<String, dynamic> _$AuthorizationStateWaitTdlibParametersToJson(
        AuthorizationStateWaitTdlibParameters instance) =>
    <String, dynamic>{};

Is there a way to get it serialized?

Most helpful comment

I'll take a look here – there may be something simple that can be done

All 12 comments

This is by design. You could mark @JsonSerializable(crateFactory: false) then all fields will be honored.

Or you could add a constructor arg for typeId and just check that it's 42.

Yes, createFactory really made the getter value serialize, but now I have no way to construct an instance of the object from JSON. The model provided in the example was just a sample, others also have data fields, so I need a way to construct them from JSON.

I understand why is design the way it is, but it would be really great if you provide an ability to mark getters as serializable, but do not use these fields in JSON when deserializing it.

Here is an example:
The model class

part 'ModelClass.g.dart';

class ModelClass
{
  ModelClass(this.intValue, this.strValue);

  factory ModelClass.fromJSON(String json) =>
    _$ModelClassFromJson(jsonDecode(json));

  String toJSON() => jsonEncode(_$ModelClassToJson(this));

  int intValue;
  String strValue;

  // onlySerialize
  // - if set to true the value is used only for serialization of the object, and ignored when deserializing JSON to the object
  // - if set to false - the behavior is the same as it is right now
  // - the dafault value is false
  @JsonKey(name: "CONSTRUCTOR", onlySerialize: true)
  int get typeID => 42;
}

Which produses ModelClass.g.dart file containing the following functions:

ModelClass _$ModelClassFromJson(Map<String, dynamic> json) {
  return ModelClass(json['intValue'] as int, json['strValue'] as String);
}

Map<String, dynamic> _$ModelClassToJson(ModelClass instance) =>
    <String, dynamic>{
      'intValue': instance.intValue,
      'strValue': instance.strValue,
      'CONSTRUCTOR': instance.typeID
    };

Is this behaviour possible to implement?

You could add the typeId to the constructor as an optional-named arg and
just ignore it – or assert it matches the expected value!

On Sun, Jun 2, 2019 at 6:58 AM Tymur Lysenko notifications@github.com
wrote:

Yes, createFactory really made the getter value serialize, but now I have
no way to construct an instance of the object from JSON. The model provided
in the example was just a sample, others also have data fields, so I need a
way to construct them from JSON.

I understand why is design the way it is, but it would be really great if
you provide an ability to mark getters as serializable, but do not use
these fields in JSON when deserializing it.

Here is an example:
The model class

part 'ModelClass.g.dart';
class ModelClass
{
ModelClass(this.intValue, this.strValue);

factory ModelClass.fromJSON(String json) =>
_$ModelClassFromJson(jsonDecode(json));

String toJSON() => jsonEncode(_$ModelClassToJson(this));

int intValue;
String strValue;

// onlySerialize
// - if set to true the value is used only for serialization of the object, and ignored when deserializing JSON to the object
// - if set to false - the behavior is the same as it is right now
// - the dafault value is false
@JsonKey(name: "CONSTRUCTOR", onlySerialize: true)
int get typeID => 42;
}

Which produses ModelClass.g.dart file containing the following functions:

ModelClass _$ModelClassFromJson(Map json) {
return ModelClass(json['intValue'] as int, json['strValue'] as String);
}
Map _$ModelClassToJson(ModelClass instance) =>
{
'intValue': instance.intValue,
'strValue': instance.strValue,
'CONSTRUCTOR': instance.typeID
};

Is this behaviour possible to implement?

—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
https://github.com/dart-lang/json_serializable/issues/496?email_source=notifications&email_token=AAAEFCU5UAWLIDTYUNEJ36TPYPGXFA5CNFSM4HSBG5ZKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWXWILI#issuecomment-498033709,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAEFCSBAM6BUFLBHWJQAE3PYPGXFANCNFSM4HSBG5ZA
.

Hi @kevmoo ,
I was having the same issue and found this thread.
I'm working with JSON:API and would love to make type's as getters or final with exact value, without needing to use the optiona-named argument trick.

Would you be willing to consider changing the designed behavior?

My first argument would be that encoding and decoding should be separated processes to provide better separation of concerns. i.e. They shouldn't depend one on another. Something like Swift has with Encodable and Decodable protocols. And what is already separated in Dart by having jsonEncode and jsonDecode.

My second argument would be that you would still be able to accomplish the current behavior just by adding @JsonKey(ignore: true), while I'm currently not able to accomplish my desired behavior by adding @JsonKey(ignore: false)

Thank you in advance,
Best, VP 😊

I'll take a look here – there may be something simple that can be done

@kevmoo You gave me some hope in your last comment. Any update on this?

Haven't got to this, sorry.

Why not just add the value to the map returned from the _$helper?

@kevmoo Will you update the code generator to do this? Or, are you suggesting manually editing the generated code?

@doc-rj-celltrak – I'm not going to update the generator for this. It's too specialized of a case. Trying to avoid adding complexity here.

Ok, thanks for your reply @kevmoo. For what it's worth, my usecase is the _typename field used by GraphQL. The only way to have a pure const data class and be able to serialize this field is the named parameter hack that you mentioned above.

@doc-rj-celltrak – I'm happy to chat w/ you more about your issue if you like. email [alias]@google.com or DM me on twitter

Was this page helpful?
0 / 5 - 0 ratings