Enum mapping with differing constant-names and constant-values

66 views Asked by At

Consider the following class:

package org.kurodev.progfrog.game.map;

import com.fasterxml.jackson.annotation.JsonValue;
import io.swagger.v3.oas.annotations.media.Schema;

@Schema(enumAsRef = true)
public enum TileType {

    WALL("X"),

    FLOOR("0"),

    VOID("#"),
    ;
    private final String identifier;

    TileType(String identifier) {

        this.identifier = identifier;
    }

    public static TileType identify(char s) {
        return identify(String.valueOf(s));
    }

    public static TileType identify(String s) {
        for (TileType value : values()) {
            if (value.matches(s))
                return value;
        }
        return null;
    }

    public static TileType identifyStrict(char s) {
        return identifyStrict(String.valueOf(s));
    }

    public static TileType identifyStrict(String s) {
        for (TileType value : values()) {
            if (value.matches(s))
                return value;
        }
        throw new MapValidationException("Unrecognised tile: " + s);
    }

    @JsonValue
    public String getIdentifier() {
        return identifier;
    }

    private boolean matches(String s) {
        return s.equals(identifier);
    }

}

When using swagger to generate the yaml it ends up looking like this: (im only showing the enum part)

    TileType:
      type: string
      enum:
      - X
      - "0"
      - '#'

If i remove the @JsonValue annotation from the getter method, it results in

    TileType:
      type: string
      enum:
      - Wall
      - Floor
      - Void

But what I am actually looking for is the following (or anything similar)

    TileType:
      type: string
      enum:
      - X
      - "0"
      - '#'
      x-enum-varnames:
        - WALL
        - FLOOR
        - VOID

so that when generating a client (for example for typescript) the code results in

export const TileType = {
    WALL: 'X',
    FLOOR: '0',
    VOID: '#'
} as const;

instead of

export const TileType = {
    X: 'X',
    _0: '0',
    Hash: '#'
} as const;

I have tried the following annotations in various constellations already: @Schema, @JsonProperty, @JsonValue, @JsonCreator, @JsonSerialize(using = SerializerClass.class) as well as writing a ModelConverter class.

@Component
public class CustomEnumConverter implements ModelConverter {

    private final ModelResolver defaultConverter;

    @Autowired
    public CustomEnumConverter(ObjectMapper objectMapper) {
        this.defaultConverter = new ModelResolver(objectMapper);
    }

    @Override
    public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator<ModelConverter> chain) {
        Schema model = defaultConverter.resolve(type, context, chain);
        if (type.getType().getTypeName().contains(TileType.class.getName())) {
            model.addExtension("x-enum-varnames", Arrays.toString(TileType.values()));
        }
        return model;
    }
}

in that last approach i was especially confident. I verified that I is being called and it writes the extension into the map, yet it does not get added to the .yaml file...

Can anyone help? I am at a loss. I hope this question is somewhat clear.

0

There are 0 answers