我想在Spring Boot应用程序中使用Jackson从YAML反序列化具有以下属性的对象:
车辆
,由Boat
和Car
Boat
也有一个适航
属性,而Car
有一个极速
。mode-of-transport:
type: boat
name: 'SS Boatface'
seaworthy: true
----
mode-of-transport:
type: car`
name: 'KITT'
top-speed: 123
使用@JsonTypeInfo
和@JsonSubTypes
在我的注释子类中,这一切都可以正常工作!
现在,我想只使用一个字符串值创建一个速记,默认情况下,它应该创建一个带有该名称的Car
:
mode-of-transport: 'KITT'
我尝试创建自己的自定义序列化程序,但在大多数相关细节上遇到了问题。如果这是正确的方法,请帮助我填写:
public class VehicleDeserializer extends StdDeserializer<Merger> {
/* Constructors here */
@Override
public Vehicle deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
if (/* it is an OBJECT */){
// Use the default polymorphic deserializer
} else if (/* it is a STRING */) {
Car car = new Car();
car.setName( /* the String value */ );
return car;
}
return ???; /* what to return here? */
}
}
我发现这两个答案很有启发性,但将其与多态类型相结合似乎会使问题变得更加困难:如何从Jackson中的自定义反序列化程序调用默认反序列化程序,并使用Jackson将其反序列化为字符串或对象
与这些问题中提供的解决方案不同的是:
因此,有一种解决方案要求您使用反序列化ProblemHandler
来处理jackson错误(因为您希望使用不同的输入解析相同的类型,使用常规方法很难实现这一点):
public class MyTest {
@Test
public void doTest() throws JsonParseException, JsonMappingException, IOException {
final ObjectMapper om = new ObjectMapper();
om.addHandler(new DeserializationProblemHandler() {
@Override
public Object handleMissingInstantiator(final DeserializationContext ctxt, final Class<?> instClass, final JsonParser p, final String msg) throws IOException {
if (instClass.equals(Car.class)) {
final JsonParser parser = ctxt.getParser();
final String text = parser.getText();
switch (text) {
case "KITT":
return new Car();
}
}
return NOT_HANDLED;
}
@Override
public JavaType handleMissingTypeId(final DeserializationContext ctxt, final JavaType baseType, final TypeIdResolver idResolver, final String failureMsg) throws IOException {
// if (baseType.isTypeOrSubTypeOf(Vehicle.class)) {
final JsonParser parser = ctxt.getParser();
final String text = parser.getText();
switch (text) {
case "KITT":
return TypeFactory.defaultInstance().constructType(Car.class);
}
return super.handleMissingTypeId(ctxt, baseType, idResolver, failureMsg);
}
});
final Container objectValue = om.readValue(getObjectJson(), Container.class);
assertTrue(objectValue.getModeOfTransport() instanceof Car);
final Container stringValue = om.readValue(getStringJson(), Container.class);
assertTrue(stringValue.getModeOfTransport() instanceof Car);
}
private String getObjectJson() {
return "{ \"modeOfTransport\": { \"type\": \"car\", \"name\": \"KITT\", \"speed\": 1}}";
}
private String getStringJson() {
return "{ \"modeOfTransport\": \"KITT\"}";
}
}
class Container {
private Vehicle modeOfTransport;
public Vehicle getModeOfTransport() {
return modeOfTransport;
}
public void setModeOfTransport(final Vehicle modeOfTransport) {
this.modeOfTransport = modeOfTransport;
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes({
@Type(name = "car", value = Car.class)
})
abstract class Vehicle {
protected String type;
protected String name;
public String getType() {
return type;
}
public void setType(final String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
@JsonTypeName("car")
class Car extends Vehicle {
private int speed;
public int getSpeed() {
return speed;
}
public void setSpeed(final int speed) {
this.speed = speed;
}
}
请注意,我使用的是JSON,而不是YAML,您还需要添加其他子类型。
这实际上比我想象的更容易解决。我得到了它使用以下工作:
public class VehicleDeserializer extends StdDeserializer<Vehicle> {
public VehicleDeserializer() {
super(Vehicle.class);
}
@Override
public Vehicle deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
if (jp.currentToken() == JsonToken.VALUE_STRING) {
Car car = new Car();
car.setName(jp.readValueAs(String.class));
return car;
}
return jp.readValueAs(Vehicle.class);
}
}
public class Transport {
@JsonDeserialize(using = VehicleDeserializer.class)
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
private Vehicle modeOfTransport;
// Getter, setters
}
这意味着默认情况下,车辆被反序列化为多态对象,除非显式指定使用我的自定义反序列化器反序列化它。如果输入不是String,则反序列化器将反过来遵从多态性。
希望这将帮助遇到此问题的人:)
我有下面的JSON,我正试图使用Jackson API反序列化它 我基本上需要一个附件类,它有一个AttachmentFile对象列表,如下所示: 如何使用自定义反序列化器实现这一点? 谢谢
I'va是一个OID接口,可以由许多具体类型实现: 现在我有一个具有两个字段的对象,一个使用抽象接口类型(OID)定义,另一个使用具体类型(MyOID)定义 我想使用jackson以不同的方式序列化/反序列化字段,无论它们是使用抽象接口类型还是具体类型定义的: 注意,被序列化,包括类型信息(多态序列化),而被序列化为文本 为此,我将OID接口注释为: 并为每个具体类型分配了类型id: 最后,对容器
我想通过扩展默认的反序列化器来创建自己的反序列化器,在其后面设置更多的值: 如您所见,我还想将此DTO母类重用于其他DTO。 我没有找到任何这样的例子。我真的是世界上第一个 反序列化的“AsUsual”(p,ctxt)应该是什么 我应该使用什么motherclass?JsonDeserializer/StdDeserializer/UntypedObjectDeserializer 反序列化程序会
如何基于json中指定的类类型,在Jackson中实现从json到Java对象的转换。 Java类型示例:
我在Jackson的自定义反序列化程序中有一个问题。我想访问默认序列化程序来填充我要反序列化到的对象。在填充之后,我将执行一些自定义操作,但首先我要使用默认的Jackson行为反序列化对象。 这是我现在有的代码。 我需要的是一种初始化默认反序列化器的方法,这样我就可以在开始我的特殊逻辑之前预填充我的POJO。 当从自定义反序列化程序内调用deserialize时,无论我如何构造序列化程序类,该方法
假设我正在为某个类编写自定义序列化,但希望使用默认方法处理其中一个字段。 那要怎么做? 序列化时,我们有。 但反序列化的相应方法是什么? 请注意以下代码: 如何实现MyOuterDeserializer?