How to manage serialize / deserialize an enum property with Dart / Flutter to Firestore? How to manage serialize / deserialize an enum property with Dart / Flutter to Firestore? dart dart

How to manage serialize / deserialize an enum property with Dart / Flutter to Firestore?


Flutter is able to generate JSON serialization code. The tutorial you can find here. It references the package json_annotation. It contains also support for enum serialization. So all you need, is use this tool and annotate your enum values with @JsonValue.

From the code docs:

An annotation used to specify how a enum value is serialized.

That's basically all. Let me now illustrate with a small example in code. Imagine an enum with vehicles:

import 'package:json_annotation/json_annotation.dart';enum Vehicle {  @JsonValue("bike") BIKE,  @JsonValue("motor-bike") MOTOR_BIKE,  @JsonValue("car") CAR,  @JsonValue("truck") TRUCK,}

Then you can use this enum in one of your model, for example vehilce_owner.dart that looks like this:

import 'package:json_annotation/json_annotation.dart';part 'vehicle_owner.g.dart';@JsonSerializable()class VehicleOwner{  final String name;  final Vehicle vehicle;  VehicleOwner(this.name, this.vehicle);  factory VehicleOwner.fromJson(Map<String, dynamic> json) =>      _$VehicleOwnerFromJson(json);  Map<String, dynamic> toJson() => _$VehicleOwnerToJson(this);}

This is what you need to provide according to the json generation howto. Now you need to run the builder or watcher to let flutter generate the code:

flutter pub run build_runner build

Then the generated code will look like as seen below. Take a look at the _$VehicleEnumMap that has been generated respecting your @JsonValue annotations:

// GENERATED CODE - DO NOT MODIFY BY HANDpart of 'vehicle_owner.dart';// **************************************************************************// JsonSerializableGenerator// **************************************************************************// more generated code omitted here ....const _$VehicleEnumMap = {  Vehicle.BIKE: 'bike',  Vehicle.MOTOR_BIKE: 'motor-bike',  Vehicle.CAR: 'car',  Vehicle.TRUCK: 'truck',};


Gunter's answer is correct if a little incomplete.

JSON serializable does handle converting Enum's to and from a string, here is some example code of what is generated:

const _$HoursEnumMap = <Hours, dynamic>{  Hours.FullTime: 'FullTime',  Hours.PartTime: 'PartTime',  Hours.Casual: 'Casual',  Hours.Contract: 'Contract',  Hours.Other: 'Other'};

and in return it converts it back with this fairly obtuse function:

T _$enumDecode<T>(Map<T, dynamic> enumValues, dynamic source) {  if (source == null) {    throw ArgumentError('A value must be provided. Supported values: '        '${enumValues.values.join(', ')}');  }  return enumValues.entries      .singleWhere((e) => e.value == source,          orElse: () => throw ArgumentError(              '`$source` is not one of the supported values: '              '${enumValues.values.join(', ')}'))      .key;}

I got so sick of this I decided to make a small package to take away the complexity, and it has come in pretty handy for me:

https://pub.dev/packages/enum_to_string

At the very least its unit tested over a copy/paste solution. Any additions or pull requests are welcome.


The way i do it is by just saving the index of the enum.

Lets say you have an enum:

enum Location {  EARTH,  MOON,  MARS,}

and a class which holds the enum with following methods:

/// Returns a JSON like Map of this User object  Map<String, dynamic> toJSON() {    return {      "name": this.name,      "location": this.location.index,    };  }  /// Returns [Player] build from a map with informationen  factory Player.fromJson(Map<String, dynamic> parsedJson) {    return new Player(      name: parsedJson['name'],      location: Location.values.elementAt(        parsedJson['location'],      ),    );  }