Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom serialization for enum type #14

Open
zett42 opened this issue Jan 1, 2020 · 0 comments
Open

Custom serialization for enum type #14

zett42 opened this issue Jan 1, 2020 · 0 comments

Comments

@zett42
Copy link

zett42 commented Jan 1, 2020

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant