How to Build a Flexible Enum Dictionary API in Java with Lambda Magic

This article explains how to design a reusable Java enum‑based dictionary API, extract common key/label properties, extend it with custom fields, and use lambda expressions together with reflection to generate clean JSON lists without hard‑coded magic strings.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
How to Build a Flexible Enum Dictionary API in Java with Lambda Magic

Background

In typical backend development we use enum dictionaries to represent types such as gender, order status, payment method, etc.

1.1 Common Enum

A standard Java enum is defined with @Getter and @AllArgsConstructor and contains key and label fields.

@Getter
@AllArgsConstructor
public enum NotifyChannel {
    WORK_WECHAT(1, "企业微信"),
    FEI_SHU(2, "飞书");
    private final int key;
    private final String label;
}

For the frontend we usually expose the data as JSON:

[
  {"key":1, "label":"企业微信"},
  {"key":2, "label":"飞书"}
]

1.2 Extended Enum

Sometimes extra attributes are needed, e.g. a color field.

@Getter
@AllArgsConstructor
public enum Gender {
    MALE(1, "男", "#409EFF"),
    FEMALE(2, "女", "#67C23A");
    private final int key;
    private final String label;
    private final String color;
}

We need an API that can return these dictionary values.

Implementation

2.1 Extract Common Properties

Define a standard interface that all enums implement:

public interface IDictionary {
    int getKey();
    String getLabel();
}

Each enum implements IDictionary and provides the required methods.

2.2 Traverse Enums

Use clazz.getEnumConstants() to iterate over all enum items.

Arrays.stream(clazz.getEnumConstants()).forEach(enumItem -> {
    // process each item
});

2.3 Dictionary Utility

Create a DictionaryUtil class to build a list of maps from the enum values.

public class DictionaryUtil {
    public static <D extends IDictionary> List<Map<String, Object>> getDictionaryList(@NotNull Class<D> clazz) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        Arrays.stream(clazz.getEnumConstants()).forEach(enumItem -> {
            Map<String, Object> item = new HashMap<>(2);
            item.put("key", enumItem.getKey());
            item.put("label", enumItem.getLabel());
            mapList.add(item);
        });
        return mapList;
    }
}

This works for the basic key / label pair but not for additional fields.

If we also need the color attribute we would have to write another method, which is inconvenient.

2.4 Overload with Custom Properties

Provide an overloaded method that accepts property names:

public static <D extends IDictionary> List<Map<String, Object>> getDictionaryLists(@NotNull Class<D> clazz, String... props) {
    List<Map<String, Object>> mapList = new ArrayList<>();
    Arrays.stream(clazz.getEnumConstants()).forEach(enumItem -> {
        Map<String, Object> item = new HashMap<>(2);
        for (String prop : props) {
            try {
                Method method = clazz.getMethod("get" + StringUtils.capitalize(prop));
                Object value = method.invoke(enumItem);
                item.put(prop, value);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        mapList.add(item);
    });
    return mapList;
}

Calling it with property names still relies on magic strings and may reference non‑existent fields.

Passing arbitrary strings as property names is not elegant and can introduce magic values.

We prefer a type‑safe approach using method references.

Lambda Optimization

Introduce a functional interface that extends Function and Serializable:

@FunctionalInterface
public interface IFunction<T, R> extends Function<T, R>, Serializable {}

Use reflection to extract the method name from a lambda expression:

public static String getLambdaFunctionName(@NotNull IFunction<?, ?> lambda) {
    try {
        Method writeReplace = lambda.getClass().getDeclaredMethod("writeReplace");
        writeReplace.setAccessible(true);
        SerializedLambda sl = (SerializedLambda) writeReplace.invoke(lambda);
        return sl.getImplMethodName().replace("get", "");
    } catch (Exception e) {
        throw new ServiceException(e);
    }
}

Now we can pass method references and automatically obtain the property names:

DictionaryUtil.getDictionaryList(ServiceError.class, ServiceError::getKey, ServiceError::getLabel);

The utility iterates over the provided lambdas, derives the property name, and puts the returned value into the map.

Arrays.stream(clazz.getEnumConstants()).forEach(enumItem -> {
    Map<String, Object> item = new HashMap<>(lambdas.length);
    Arrays.stream(lambdas).forEach(lambda -> {
        try {
            String prop = StringUtils.uncapitalize(ReflectUtil.getLambdaFunctionName(lambda));
            item.put(prop, lambda.apply(enumItem));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    });
    mapList.add(item);
});

Finally, the API can be used elegantly:

DictionaryUtil.getDictionaryList(ServiceError.class);
DictionaryUtil.getDictionaryList(ServiceError.class, ServiceError::getKey, ServiceError::getLabel);
DictionaryUtil.getDictionaryList(UserGender.class, UserGender::getKey, UserGender::getLabel, UserGender::getColor);

Summary

The article demonstrates a clean, type‑safe way to expose enum dictionaries as JSON lists in Java, evolving from a simple key/label implementation to a flexible lambda‑based solution that avoids magic strings and supports arbitrary enum fields.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ReflectionLambdaenumDictionary API
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.