Decorated Enums — another way of serialising Enums in Dart

Nic Ford
Flutter Community
Published in
3 min readSep 5, 2020
Buddhist prayer flags. No idea why google thought this was related…

Luke Urban has written a really good article on ways of serialising enums in Dart, and I urge you to read that before coming back here:

This article is sort of a response to that: not because there’s anything wrong there (far from it), but because it made me start to think about the approaches I normally take, and more importantly, why.

The Simple Approach

Dart provides a pretty clean and simple way of serialising enums in the first place, assuming you don’t care whether or not your json is easily human readable: the index of the enum value, and the values of the enum class.

When an enum is declared, each value is given an index field:

enum Colours { red, green, blue }

Here red is implicitly assigned the index 0, green the index 1 and blue the index 2.

Theses indices can be used to reference the value within the values list of the enum itself:

print(Colours.values[1]);
> Colours.green

And so, it’s easy to see how this naively gives us a way to serialise the enum. To use Luke’s car example:

One downside of this approach is that the resultant json now has an integer in the brand field rather than a string, which is less easy to interpret for any humans reading:

{
id: 1,
name: 'Cinquecento',
brand: 6
}

where 6 represents Fiat, but not all that obviously.

A greater downside is that, should the order of members of the enum change between serialisation and deserialisation, we’re stuffed: the index no longer refers to the correct value.

enum Colours { cyan, magenta, yellow, red, green, blue }print(Colours.values[1]); // was 'Colours.green' before
> Colours.magenta

So I often find myself creating what I tend to think of as Decorated Enums.

The Far More Complicated For No Good Reason Approach: Decorated Enums

Sometimes I want to be able to fiddle with the order of values in an enum, and augment (‘decorate’) them with extra functionality. Treat the enum like a class, in fact. And there is, of course, a pretty easy way to do that:

For me, the downside here is that there’s a fair bit of boiler plate to get it all up and running. (I’ve tried various things: auto-adding an instance to the values list on creation, for example [which fails because of Dart’s lazy object creation]; or using a map of name to object for the values [which I didn’t like because of even more repetition of the name string — YMMV]; and so on).

However, I think it’s worth it, not least because there are advantages in adding functionality to the enum itself. Where something lives in the brand, it should be found in the brand IMHO.

And there you have it. No more deserialisation problems if the order of the enum changes, and a bit of extra functionality living where it should in the enum, isGood. The downside of the extra boiler plate is worth living with, IMHO. Again, YMMV.

Thanks for reading. Keep playing with Flutter.

https://www.twitter.com/FlutterComm

--

--