Heikkisorsa
Heikkisorsa

Reputation: 905

Parse enum from json

I have an enum

enum Mode { standard, relative, fixed }

extension ModeMap on Mode {
  static const valueMap = {
    Mode.standard: "standard",
    Mode.relative: "relative",
    Mode.fixed: "fixed",
  };
  String? get value => valueMap[this];
}

And a model using this enum with a method fromJson:

class Settings {
  Mode mode;
  String name;

  Settings({
    required this.mode,
    required this.name,
  });

  Settings.fromJson(Map<String, dynamic> json)
      : mode = Mode[json['Mode'].toString()] as Mode,
        name = json['Name'],


  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['Mode'] = mode.value;
    data['Name'] = name;
    return data;
  }
}

However, it seems that I can't transform the values from json to my enum this way. What is the proper way to do this?

Upvotes: 1

Views: 1099

Answers (1)

Christopher Moore
Christopher Moore

Reputation: 17143

You could do the reverse of what you did with the value getter. The following code makes a fromString method to get a Mode from a String by reversing your valueMap. You then can use it with ModeMap.fromString(json['Mode']) in your factory constructor.

enum Mode { standard, relative, fixed }

extension ModeMap on Mode {
  static const valueMap = {
    Mode.standard: "standard",
    Mode.relative: "relative",
    Mode.fixed: "fixed",
  };
  String? get value => valueMap[this];
  
  static Mode fromString(String input) {
    final reverseValueMap = valueMap.map<String, Mode>((key, value) => MapEntry(value, key));
    
    Mode? output = reverseValueMap[input];
    if(output == null) {
      throw 'Invalid String Input';
    }
    
    return output;
  }
}

class Settings {
  Mode mode;
  String name;

  Settings({
    required this.mode,
    required this.name,
  });

  Settings.fromJson(Map<String, dynamic> json)
      : mode = ModeMap.fromString(json['Mode']),
        name = json['Name'];


  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['Mode'] = mode.value;
    data['Name'] = name;
    return data;
  }
}

Upvotes: 2

Related Questions