[英]Jackson @JsonValue annotation selectively override or disable
我有一个具有以下属性的枚举:
private Integer id;
private String name;
private String description;
这个枚举有一个带有 Jackson 的 @JsonValue 注释的函数:
@JsonValue
public String toValue() {
return Stream.of(values())
.filter(eventType -> eventType == this)
.findAny()
.map(EventType::toString)
.orElseThrow(() -> new IllegalArgumentException("Unable to convert EventType to value:" + this));
}
这按需要执行,将枚举值序列化为 toString 返回的值,即枚举的名称。
我希望能够禁用 @JsonValue 注释,并且只使用 Jackson 附加到此类的默认 JSON 序列化行为: @JsonFormat(shape = JsonFormat.Shape.OBJECT)
在某些情况下必须获取代表整个枚举的对象,而不仅仅是名字。
杰克逊似乎没有内置这种能力(或者我不太了解它)。 我无法创建扩展此类的包装类,因为 Java 不允许使用枚举。
有什么建议?
这可以使用 Mixin 来实现。
保持你的枚举类相同,创建一个混合类:
// MyEnumMixin.java
import com.fasterxml.jackson.annotation.JsonValue;
public abstract class MyEnumMixin {
@JsonValue(false)
public abstract String toValue();
}
然后在创建 Mapper 时添加 mixin
// MyService.java
...
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(MyEnum.class, MyEnumMixin.class);
return mapper.writeValueAsString(pojoWithEnum);
...
感谢https://stackoverflow.com/users/6911095/ldz帮助我解决类似问题并能够在此处添加答案。 https://stackoverflow.com/a/59459177/7589862
我没有想到一个现成的解决方案,但是我能想到的最接近的选择是针对此特定枚举类型使用自定义序列化程序。
添加自定义序列化器很容易,只需要扩展一个JsonSerializer
类并实现serialize
方法,然后在所需的类型中使用@JsonSerialize
批注中的类即可(并且您不需要@JsonValue
)。 枚举对象将被传递到serialize
方法中,在那里您可以选择编写toString
或toValue
。
下面提供了示例代码以及输出。
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.io.IOException;
import java.util.stream.Stream;
public class SOQuestion {
static ThreadLocal<Boolean> USE_TO_STRING = ThreadLocal.withInitial(() -> false);
@JsonSerialize(using = MySerializer.class)
enum EventType{
ONE(1, "One", "Just One"), TWO(2, "Two", "Just Two");
private Integer id;
private String name;
private String description;
EventType(Integer id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
}
public String toValue() {
return Stream.of(values())
.filter(eventType -> eventType == this)
.findAny()
.map(EventType::toString)
.map(s -> "toValue="+s)
.orElseThrow(() -> new IllegalArgumentException("Unable to convert EventType to value:" + this));
}
}
@Data
@AllArgsConstructor
static class Dummy{
int someNum;
EventType eventType;
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Dummy dummy = new Dummy(100, EventType.ONE);
System.out.println("**** DEFAULT *****");
System.out.println(objectMapper.writeValueAsString(dummy));
System.out.println("**** toString *****");
USE_TO_STRING.set(true);
System.out.println(objectMapper.writeValueAsString(dummy));
}
private static class MySerializer extends JsonSerializer<EventType> {
@Override
public void serialize(EventType value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
if(USE_TO_STRING.get()){
gen.writeString(value.toString());
}else{
gen.writeString(value.toValue());
}
}
}
}
输出:
**** DEFAULT *****
{"someNum":100,"eventType":"toValue=ONE"}
**** toString *****
{"someNum":100,"eventType":"ONE"}
使用龙目岛的道歉让事情变得简单。 如果您不熟悉,那么该找它了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.