Mehmet Karanlık
Mehmet Karanlık

Reputation: 277

Is there a way to return different key names for toJson and fromJson methods, json_serializable

Is it possible to use json_serializable and have different key names for same field for toJson and fromJson.

ex json-data:

{
"idUser": 123,
/// some other fields
}

incoming json_data from another APIs

{
"id" : 123,
/// some other fields
}
@JsonSerializable()
class Id extends INetworkModel<Id> {
  Id(this.idUser);

  final int? idUser;

  @override
  Id fromJson(Map<String, dynamic> json) => _$IdFromJson(json);

  @override
  Map<String, dynamic>? toJson() => _$IdToJson(this);
}

for that particular id field, I want to map it as idUser for toJson and id as fromJson.

based on what I saw for json_serializable docs it's possible to manipulate field values with custom toJson and fromJson methods but didn't see any other option to manipulate key names in JSON based on the method.

I would be very glad if someone enlightens me thanks ahead!

Upvotes: 2

Views: 890

Answers (3)

Daud
Daud

Reputation: 19

The readValue parameter in JsonKey can be used to differentiate the key used for fromJson from the main one which is used for toJson.

@JsonSerializable()
class Id extends INetworkModel<Id> {
  Id(this.idUser);

  // Create a static method for `readValue`
  static int? readId(Map<dynamic, dynamic> json, String name) {
    // When used by `idUser` in this context, `name` would be "idUser".
    // We can ignore that and just grab a value from the key that we want.
    return json["id"];
  }

  // "idUser" or whatever name given in the `JsonKey`'s `name` parameter will still be used for `toJson`.
  @JsonKey(readValue: readId)
  final int? idUser;

  @override
  Id fromJson(Map<String, dynamic> json) => _$IdFromJson(json);

  @override
  Map<String, dynamic>? toJson() => _$IdToJson(this);
}

Upvotes: 0

Azhar Husain Raeisi
Azhar Husain Raeisi

Reputation: 197

Not recommended, however you can do

Go to yourfile.g.dart

part of 'yourfile.dart';

as you stated that I want to map it as idUser for toJson and id as fromJson.

Id _$IdFromJson(Map<String, dynamic> json) => Id(
      idUser: json['id'] as int,
     // your rest of fields
    );

Map<String, dynamic> _$IdToJson(Id instance) => <String, dynamic>{
      'id': idUser,
      // your rest of fields
    };

Upvotes: 0

Jared Anderton
Jared Anderton

Reputation: 1026

An alternative approach to having 2 sources for the same property:

Parse both as nullable, and have a getter to retrieve the value. Something like:

@JsonSerializable()
class Id extends INetworkModel<Id> {
  Id(this.idUser, this.id);

  final int? idUser;
  final int? id;
  int? get theUserId => id ?? isUser;


  @override
  Id fromJson(Map<String, dynamic> json) => _$IdFromJson(json);

  @override
  Map<String, dynamic>? toJson() => _$IdToJson(this);
}

Upvotes: 1

Related Questions