Enumeration from string

I have an Enum and a function to create it from String , because I could not find a built-in way to do this

 enum Visibility{VISIBLE,COLLAPSED,HIDDEN} Visibility visibilityFromString(String value){ return Visibility.values.firstWhere((e)=> e.toString().split('.')[1].toUpperCase()==value.toUpperCase()); } //used as Visibility x = visibilityFromString('COLLAPSED'); 

but it seems that I should rewrite this function for each Enum I have, is there a way to write the same function where the Enum type is used as a parameter? I tried, but I realized that I can not use Enum.

 //is something with the following signiture actually possible? dynamic enumFromString(Type enumType,String value){ } 
+12
source share
10 answers

Using mirrors can lead to some behavior. I had two ideas. Unfortunately, Dart does not support typed functions:

 import 'dart:mirrors'; enum Visibility {VISIBLE, COLLAPSED, HIDDEN} class EnumFromString<T> { T get(String value) { return (reflectType(T) as ClassMirror).getField(#values).reflectee.firstWhere((e)=>e.toString().split('.')[1].toUpperCase()==value.toUpperCase()); } } dynamic enumFromString(String value, t) { return (reflectType(t) as ClassMirror).getField(#values).reflectee.firstWhere((e)=>e.toString().split('.')[1].toUpperCase()==value.toUpperCase()); } void main() { var converter = new EnumFromString<Visibility>(); Visibility x = converter.get('COLLAPSED'); print(x); Visibility y = enumFromString('HIDDEN', Visibility); print(y); } 

Outputs:

 Visibility.COLLAPSED Visibility.HIDDEN 
+6
source

Mirrors are not always available, but, fortunately, you do not need them. It is compact enough and should do what you want.

 enum Fruit { apple, banana } // Convert to string String str = Fruit.banana.toString(); // Convert to enum Fruit f = Fruit.values.firstWhere((e) => e.toString() == str); assert(f == Fruit.banana); // it worked 

Fix: As @frostymarvelous mentioned in the comments section, this is the correct implementation:

 Fruit f = Fruit.values.firstWhere((e) => e.toString() == 'Fruit.' + str); 
+27
source

Collin Jackson's solution does not work for me, because Dart is building enums in EnumName.value and not just value (like Fruit.apple ), and I tried to convert the value of a string like apple and not convert Fruit.apple from get-go.

With that in mind, this is my solution for listing from a string task

 enum Fruit {apple, banana} Fruit getFruitFromString(String fruit) { fruit = 'Fruit.$fruit'; return Fruit.values.firstWhere((f)=> f.toString() == fruit, orElse: () => null); } 
+4
source

There are several enumeration packages that allowed me to get only an enumeration string, not a type.value string (Apple, not Fruit.Apple).

https://pub.dartlang.org/packages/built_value (this is more relevant)

https://pub.dartlang.org/packages/enums

 void main() { print(MyEnum.nr1.index); // prints 0 print(MyEnum.nr1.toString()); // prints nr1 print(MyEnum.valueOf("nr1").index); // prints 0 print(MyEnum.values[1].toString()) // prints nr2 print(MyEnum.values.last.index) // prints 2 print(MyEnum.values.last.myValue); // prints 15 } 
+1
source

I had the same problem with creating objects from JSON. There are strings in JSON values, but I wanted enum to check if the value is correct. I wrote this helper that works with any enumeration, not the specified one:

 class _EnumHelper { var cache = {}; dynamic str2enum(e, s) { var o = {}; if (!cache.containsKey(e)){ for (dynamic i in e) { o[i.toString().split(".").last] = i; } cache[e] = o; } else { o = cache[e]; } return o[s]; } } _EnumHelper enumHelper = _EnumHelper(); 

Using:

 enumHelper.str2enum(Category.values, json['category']); 

PS. I have not used types here. enum is not a type in Dart and is considered a complex process. The class is used exclusively for caching.

+1
source

My solution is identical to Rob C's solution, but without string interpolation:

 T getEnumFromString<T>(Iterable<T> values, String value) { return values.firstWhere((type) => type.toString().split(".").last == value, orElse: () => null); } 
+1
source

@Collin Jackson has a very good IMO answer. I used a for-in loop to achieve a similar result before searching for this question. I am definitely switching to using the firstWhere method.

Extending his answer is what I did to eliminate the type from value strings:

 enum Fruit { apple, banana } class EnumUtil { static T fromStringEnum<T>(Iterable<T> values, String stringType) { return values.firstWhere( (f)=> "${f.toString().substring(f.toString().indexOf('.')+1)}".toString() == stringType, orElse: () => null); } } main() { Fruit result = EnumUtil.fromStringEnum(Fruit.values, "apple"); assert(result == Fruit.apple); } 

Maybe someone will find this useful ...

0
source

Here is a function that converts a given string to an enum type:

 EnumType enumTypeFromString(String typeString) => EnumType.values .firstWhere((type) => type.toString() == "EnumType." + typeString); 

And here is how you convert this type of enumeration into a string:

 String enumTypeToString(EnumType type) => type.toString().split(".")[1]; 
0
source

I think my approach is a little different, but in some cases it may be more convenient. Finally, we have parse and tryParse for enumerated types:

 import 'dart:mirrors'; class Enum { static T parse<T>(String value) { final T result = (reflectType(T) as ClassMirror).getField(#values) .reflectee.firstWhere((v)=>v.toString().split('.').last.toLowerCase() == value.toLowerCase()) as T; return result; } static T tryParse<T>(String value, { T defaultValue }) { T result = defaultValue; try { result = parse<T>(value); } catch(e){ print(e); } return result; } } 

EDIT: this approach DOES NOT work in Flutter applications, by default mirrors are locked in Flutter, because this leads to the generated packages being very large.

0
source

I had the same problem in one of my projects and the existing solutions were not very clean and it did not support advanced features like json serialization / deserialization.

Flutter did not initially support enum with values, however I managed to develop a Vnum helper package using a class implementation and reflectors to solve this problem.

Contact the repository:

https://github.com/AmirKamali/Flutter_Vnum

To answer your problem with Vnum , you can implement your code like Vnum below:

 @VnumDefinition class Visibility extends Vnum<String> { static const VISIBLE = const Visibility.define("VISIBLE"); static const COLLAPSED = const Visibility.define("COLLAPSED"); static const HIDDEN = const Visibility.define("HIDDEN"); const Visibility.define(String fromValue) : super.define(fromValue); factory Visibility(String value) => Vnum.fromValue(value,Visibility); } 

You can use it like:

 var visibility = Visibility('COLLAPSED'); print(visibility.value); 

The github repository has more documentation, hope it helps you.

0
source

Source: https://habr.com/ru/post/1209977/


All Articles