[英]How to serialise Enums as both Object Shape and default string?
對於具有屬性的枚舉,例如:
public enum Thing {
THING_A("a"),
THING_B("b");
private String thing;
private Thing(String thing) {
this.thing = thing;
}
// Getters...
}
Jackson
序列化為值的名稱,例如:
mapper.writeValueAsString(Thing.THING_A)); // "THING_A"
如果我們添加注釋以將序列化視為 object:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
它將序列化屬性:
mapper.writeValueAsString(Thing.THING_A)); // "{"thing":"a"}"
我希望能夠在序列化期間決定使用哪些方法。 因為這跨越了大量的枚舉,我寧願不編輯每一個。 有沒有好的方法來做到這一點?
例如:這樣的事情會很棒:
mapper.writeValueAsString(Thing.THING_A, JsonFormat.Shape.OBJECT); // "{"thing":"a"}"
mapper.writeValueAsString(Thing.THING_A, JsonFormat.Enum.DEFAULT); // "THING_A"
上面的問題是類似的,已經回答了。 Jackson ObjectMapper 設置 JsonFormat.Shape.ARRAY 無注釋。
您可以使用特定於 Enum 的自定義 object 映射器和其他類的不同 object 映射器。
Since, com.fasterxml.jackson.annotation.JsonFormat
is an annotation you can implement your own com.fasterxml.jackson.databind.AnnotationIntrospector
and return value you want for all your enums. 您可以在下面找到簡單的示例:
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
public class JsonPathApp {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(AnnotationIntrospector.pair(new DynamicEnumAnnotationIntrospector(), new JacksonAnnotationIntrospector()));
System.out.println(mapper.writeValueAsString(Thing.THING_A));
}
}
class DynamicEnumAnnotationIntrospector extends AnnotationIntrospector {
@Override
public Version version() {
return new Version(1, 0, 0, "Dynamic enum object", "your.package", "jackson.dynamic.enum");
}
@Override
public JsonFormat.Value findFormat(Annotated memberOrClass) {
final Class<?> rawType = memberOrClass.getRawType();
if (rawType.isEnum() && rawType.getPackage().getName().startsWith("your.package")) {
return JsonFormat.Value.forShape(JsonFormat.Shape.OBJECT);
}
return super.findFormat(memberOrClass);
}
}
上面的代碼打印:
{"thing":"a"}
現在,您可以創建兩個ObjectMapper
實例,一個配置您自己的注釋內省,第二個保留默認值。 如果您真的想以動態方式使用它,您可以為每個可用的Shape
值創建一個ObjectMapper
,並且 select 需要一個給定形狀:
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
import java.util.Objects;
public class JsonPathApp {
public static void main(String[] args) throws Exception {
JsonFactory factory = new JsonFactory();
for (Shape shape : Shape.values()) {
ObjectMapper mapper = factory.getWithEnumShapeSetTo(shape);
System.out.println(shape + " => " + mapper.writeValueAsString(Thing.THING_A));
}
}
}
class JsonFactory {
private final AnnotationIntrospector defaultIntrospector = new JacksonAnnotationIntrospector();
private final EnumMap<Shape, ObjectMapper> instances = new EnumMap<>(Shape.class);
public JsonFactory() {
final List<Shape> notAllowed = Arrays.asList(Shape.BOOLEAN, Shape.BINARY);
Arrays.stream(Shape.values())
.filter(shape -> !notAllowed.contains(shape))
.forEach(shape -> instances.put(shape, createNewWithEnumShape(shape)));
}
private ObjectMapper createNewWithEnumShape(Shape shape) {
DynamicEnumAnnotationIntrospector enumIntrospector = new DynamicEnumAnnotationIntrospector(shape);
ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(AnnotationIntrospector.pair(enumIntrospector, defaultIntrospector));
return mapper;
}
public ObjectMapper getWithEnumShapeSetTo(Shape shape) {
Objects.requireNonNull(shape);
final ObjectMapper mapper = instances.get(shape);
if (mapper == null) {
return new ObjectMapper();
}
return mapper;
}
}
class DynamicEnumAnnotationIntrospector extends AnnotationIntrospector {
private final Shape shape;
public DynamicEnumAnnotationIntrospector(Shape shape) {
this.shape = Objects.requireNonNull(shape);
}
@Override
public Version version() {
return new Version(1, 0, 0, "Dynamic enum shape", "your.package", "jackson.dynamic.enum");
}
@Override
public JsonFormat.Value findFormat(Annotated memberOrClass) {
final Class<?> rawType = memberOrClass.getRawType();
if (rawType.isEnum() && rawType.getPackage().getName().startsWith("your.package")) {
return JsonFormat.Value.forShape(shape);
}
return super.findFormat(memberOrClass);
}
}
上面的代碼打印:
ANY => "THING_A"
NATURAL => "THING_A"
SCALAR => "THING_A"
ARRAY => 0
OBJECT => {"thing":"a"}
NUMBER => 0
NUMBER_FLOAT => 0
NUMBER_INT => 0
STRING => "THING_A"
BOOLEAN => "THING_A"
BINARY => "THING_A"
上面的代碼當然是矯枉過正,但我想展示我們擁有的可能性。 我們只有 3 個不同的輸出,因此您可以使用相同的 output 對值進行分組,並創建最多 3 個不同的ObjectMappers
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.