Skip to content

Custom serialization for enum type #14

@zett42

Description

@zett42

I wanted to do something like this to define custom enum serialization (e. g. to serialize enum value as string instead of number):

@Serialize.Type({ ... })
enum MyEnum { a, b, c }

Unfortunately this doesn't work, because TS compiler says "Decorators are not valid here".

As a workaround we can wrap the enum inside a class. Then we can add decorator to the wrapper class. Maybe this is something you want to add to your library?

Here is the code of my TS module (2 files including Jest unit tests):
https://gist.github.com/zett42/bbd427e66cfabe3045ed73761d386a91

Usage example for serialization:

enum BallSizeEnum {
    little,
    normal,
    big, 
}

@SerializeEnumWrapper( BallSizeEnum )
// By default, enum is serialized as the string key. To serialize as the value:
//@SerializeEnumWrapper( BallSizeEnum, { serializeAsKey: false } )
class BallSize {
    constructor( public value: BallSizeEnum = BallSizeEnum.normal ) {}
}

class Ball {
    @Serialize() size: BallSize = new BallSize( BallSizeEnum.big );
}

Usage example for reflection:
(requires TS compiler option emitDecoratorMetadata)

enum BallSizeEnum {
    little,
    normal,
    big, 
}

@SerializeEnumWrapper( BallSizeEnum, {
    // Add optional meta data per enum key. Values can be anything. 
    valuesDescriptor: {
        little: "Little Ball",
        normal: "Normal Ball",
        big: { more: "info" },
    } 
})
class BallSize {
    constructor( public value: BallSizeEnum = BallSizeEnum.normal ) {}
}

const ballSize = new BallSize;

console.log( getEnumValuesMetadata( ballSize ) );
// ... prints {0: "little", 1: "normal", 2: "big", little: 0, normal: 1, big: 2}

console.log( getEnumValuesDescriptorMetadata( ballSize ) );
// ... prints {little: "Little Ball", normal: "Normal Ball", big: {…}}

Revisions of this post:
Jan-05-2020

  • Moved code to Gist
  • Support string enums
  • Override standard methods valueOf(), toString() and toJSON() of the prototype of the wrapper class to "unwrap" the native enum value. Add option 'toJsonAsKey' so that toJSON() writes the key instead of the value (default).
  • Add unit tests (Jest).

Jan-03-2020

  • Made the decorator function typesafe:
    • A compile error gets raised if the 'value' property of the wrapper class is of a different enum type than what is passed to the decorator function.
    • When the valuesDescriptor option is specified, ist must have a property for each enum key. Otherwise a compile error gets raised.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions