json_serializable flutter parse and map with key connect with modal and mapper

792 Views Asked by At

Thais is my json format


"recommended": {
            "section_title": "Recommended",
            "section_sub_title": "Recommended",
            "data": {
                "Allahabad": [
                    {
                        "gym_id": "9",
                        "name": "raga fitness",
                        "address": "35 Vivekanand Marg Hewett Road Allahabad",
                        "city_id": "1565",
                        "gym_logo": "http://139.180.218.66/gym/resources/alias_raga_fitness_20220403165957.jpeg",
                        "no_of_ratings": null,
                        "total_ratings": null,
                        "average_ratings": null,
                        "city_name": "Allahabad"
                    }
                ],
                "Lucknow": [
                    {
                        "gym_id": "2",
                        "name": "Gym Name 2",
                        "address": "gym address",
                        "city_id": "1496",
                        "gym_logo": "http://139.180.218.66/gym/resources/alias_Gym_Name_20220127182703.jpeg",
                        "no_of_ratings": "16",
                        "total_ratings": "55.5",
                        "average_ratings": "3.5",
                        "city_name": "Lucknow"
                    }
                ]
            }
        }

i use json_serializable, dio, and json_annotation want to be mapped with modal and ResponseMapper

I am using json_serializable in Flutter to store a class in a file and read back from it. I am not posting the original class here for simplicity, but the principle is that half way through writing the app I decided that I wanted to change the variable name "aStupidName" to "name". How can I advise the code generation utility to assign the JSON value with the key "aStupidName", if it exists in the JSON, to the variable "name", but if the key "name" exists to assign this to the variable instead, i.e. in newer versions of the file?

1

There are 1 best solutions below

0
On

Solution 1

In the model class, let's say XYZ, use the @JsonKey to map a how a field is read from JSON. This can be done with JsonKey.readValue that takes 2 arguments: the JSON data as Map<String, dynamic> and the field name. It's going to be something like the following. Also, check out the official docs.

import 'package:json_annotation/json_annotation.dart';

part 'xyz.g.dart';

Object? mapper(json, field) => json['name'] ?? json['aStupidName'];

@JsonSerializable(explicitToJson: true)
class XYZ {
  @JsonKey(readValue: mapper)
  String name;
  XYZ({required this.name});

  factory XYZ.fromJson(Map<String, dynamic> json) => _$XYZFromJson(json);
  Map<String, dynamic> toJson() => _$XYZToJson(this);
}

I'd also recommend normalizing the API/DB/whatever itself to be always name so there is no need to annotate this way.

Solution 2

On the other hand, it's possible to implement the serialization/deserialization by hand like the following. Just use the ?? operator conditional expression between name and aStupidName.

@JsonSerializable()
class XYZ {

  final String name;

  ...

  XYZ.fromJson(Map<String, dynamic> json)
    : name = json['name'] ?? json['aStupidName'],
    ...;

  Map<String, dynamic> toJson() => {
      'name': name,
      ...
  };
}