在一个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的新手,这是我第一次使用反射,在开始学习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);
}
答案 0 :(得分:1)
通常的方法是通过使用注释@JsonFormat(shape = JsonFormat.Shape.OBJECT)
或通过使用定制的序列化程序。
假设您引用的是A类的枚举
class A {
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
private Colors color;
}
这将使颜色按照您想要的方式进行序列化。
替代方法是为您的Enum注册一个自定义序列化程序,您可以通过以下方式进行操作:
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);
答案 1 :(得分:1)
有一些可以改进的地方:
您正在此行上使用原始类型:
List<HashMap<String, Object>> enumValues = new ArrayList();
应该是:
List<HashMap<String, Object>> enumValues = new ArrayList<>();
字母不一定总是以get
开头。例如,isAwesome
的吸气剂可以命名为isAwesome
。确保同样处理。或者,只获取字段值,而不是获取方法。