java - Java中枚举的每个值的键值映射

标签 java performance

任务

在一个 Java 后端项目中,我有一些(100 多个)我无法编辑的外部枚举,我需要将它们输出到我们的前端。我想以类似 JSON 对象的方式输出它们。每个枚举都有不同的属性名称。

例如对于以下枚举

public enum Colors {
  RED(1, "RED", "ff0000", Boolean.TRUE),
  GREEN(2, "GREEN", "00ff00", Boolean.FALSE),
  BLUE(3, "BLUE", "0000ff", Boolean.TRUE);

  private int code;
  private String label;
  private String hexCode;
  private boolean isAwesome;

  // ... getters and other methods
}

我要输出

[
  {
    label: "RED"
    hexCode: "ff0000"
    isAwesome: true
  },
  {
    label: "GREEN"
    hexCode: "00ff00"
    isAwesome: false
  },
  ...
]

我的尝试

我是 Java 的新手,这是我第一次使用反射,在开始之前我并没有真正学习任何东西。这段代码可能存在一些主要问题(比如性能或其他一些我不知道的奇怪的东西),但它编译并完成了工作。我不知道这是否安全,所以我想问一下是否有更好的方法来做到这一点。

private <T> List<HashMap<String, Object>> enumInserter(Class<T> clazz, List<String> properties) {
    return valuesToMap(clazz.getEnumConstants(), parserFactory(clazz, properties));
}

/**
* 
* @param <T>    type of the enum class
* @param values enumConstants of the enum
* @param parser a function that take a single enumValue of type <T> and returns
*               an property-value map
* @return the array of the property-value maps of each value
*/
private <T> List<HashMap<String, Object>> valuesToMap(T[] values, Function<T, HashMap<String, Object>> parser) {
  List<HashMap<String, Object>> enumValues = new ArrayList<>();
  for (T enumValue : values) {
    HashMap<String, Object> processedValue = parser.apply(enumValue);
    enumValues.add(processedValue);
  }
  return enumValues;
}

/**
* 
* @param <T>        the type of the enum class
* @param clazz      the enum class
* @param properties the properties to be added in the map
* @return a parser function that take a single enumValue of type <T> as input and
*         returns a property-value map of the given enumValue
*/
private <T> Function<T, HashMap<String, Object>> parserFactory(Class<T> clazz, List<String> properties) {
  return ((T enumValue) -> {
    HashMap<String, Object> map = new HashMap<>();

    properties.stream().forEach(propertyName -> {
      String methodName = getterFromProperty(propertyName);
      try {
        Method method = clazz.getMethod(methodName);
        Object methodResult = method.invoke(enumValue);
        map.put(propertyName, methodResult);
      } catch (Exception e) {
        // ... error logging
      }
    });

    return map;
  });
}

/**
* Return the "standard" property getter of a property. e.g. "example" will
* return "getExample"
* 
* @param property
* @return property getter method name
*/
private String getterFromProperty(String property) {
  return "get" + property.substring(0, 1).toUpperCase() + property.substring(1);
}

最佳答案

通常的方法是通过使用注释 @JsonFormat(shape = JsonFormat.Shape.OBJECT) 或通过使用定制的序列化程序。

假设您正在引用 A 类的枚举

class A {

   @JsonFormat(shape = JsonFormat.Shape.OBJECT)
   private Colors color;

}

这将使颜色按照您想要的方式序列化。

另一种方法是为您的枚举注册一个自定义序列化程序,您可以通过以下方式进行:

public class ColorSerializer extends StdSerializer {

    public ColorSerializer() {
        super(Color.class);
    }

    public ColorSerializer(Class t) {
        super(t);
    }

    public void serialize(Color color, JsonGenerator generator,
      SerializerProvider provider) 
      throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeFieldName("code");
        generator.writeString(color.getCode());
        generator.writeFieldName("hexCode");
        generator.writeString(color.getHexcode());
        generator.writeFieldName("isAwsome");
        generator.writeNumber(color.isAwsome());
        generator.writeEndObject();
    }
}

由于您的枚举是外部的,您始终可以将它们放在项目内部的包装器中,这样可以控制它们的序列化过程。

如果您想使用相同的策略序列化它们,您可以将反射代码放入序列化程序中。这样您将获得一个通用序列化程序,而不是为每个枚举编写。

这是注册自定义序列化程序的方法:

ObjectMapper mapper = new ObjectMapper();

SimpleModule module = new SimpleModule();
module.addSerializer(Color.class, new ColorSerializer ());
mapper.registerModule(module);

关于java - Java中枚举的每个值的键值映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56392834/

相关文章:

java - 如何使用 Vaadin 的上传方法读取图片?

java - PriorityQueue 和三元运算符

Java For-Loop - 终止表达式速度

mysql - 选择 1 个具有复杂过滤的随机行

c++ - OpenCV Python 通过图像数据绑定(bind)非常慢的迭代

performance - 图像需要很长时间才能加载 WinRT XAML

sql - 为什么 MongoDB 比 SQL DB 快得多的任何详细和具体原因?

java - 映射输出记录和减少输入记录之间的关系是什么

java - 部署后无法访问 Google App Engine 中的 Spring Boot 应用程序

java - ActiveMQ 给出 : "Could not connect to broker URL: tcp://localhost:61616" after around 10 000 messages