使用Jackson处理包含多个对象类的json数组



我从web服务接收JSON数组,该数组包含两种类型的对象-基类和扩展基类的类(它包含一些额外的属性)。我如何用Jackson处理它,它将在最后生成一个Java基类列表。例如,我有一个类Car和类Truck,其中包含Car没有的属性maxLoad(以及其他一些)。最后我需要得到List<汽车>将包含Car和Truck的实例。这是代码:

public class Car {
private String make;
private String model;
private short  year;
private String bodyStyle;
private String engineType;
private int    horsepower;
// setters and getters are omitted
}
public class Truck extends Car {
private double  maxLoad;
private double  clearance;
// setters and getters are omitted
}

这里是测试JSON文件和测试代码:

[
{
"make": "Ford",
"model": "Focus",
"year": 2018,
"engineType": "T4",
"bodyStyle": "hatchback",
"horsepower": 225
},
{
"make": "Toyota",
"model": "Prius",
"year": 2021,
"engineType": "T4",
"bodyStyle": "hatchback",
"horsepower": 121        
},
{
"make": "Toyota",
"model": "RAV4",
"year": 2020,
"engineType": "V6",
"bodyStyle": "SUV",
"horsepower": 230        
},
{
"make": "Toyota",
"model": "Tacoma",
"year": 2021,
"engineType": "V6",
"bodyStyle": "pickup",
"horsepower": 278,
"maxLoad": 1050,
"clearance": 9.4
},
{
"make": "Ford",
"model": "T150",
"year": 2017,
"horsepower": 450,
"bodyStyle": "pickup",
"maxLoad": 2320,
"clearance": 8.4
}   
]
public class Test {
private static final ObjectMapper mapper = new ObjectMapper();
@SuppressWarnings("CallToPrintStackTrace")
public static void main(String[] args) {
InputStream src = Test.class.getClassLoader().getResourceAsStream("cars.json");
try {
List<Car> cars = mapper.readValue(src, new TypeReference<List<Car>>() {});
for (Car car : cars) {
System.out.println(car.getClass().getName());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

当我运行这个测试程序时,我得到了一个异常:

com.fasterxml.jackson.databind.exc.UnrecognitedPropertyException:无法识别的字段"maxLoad";(class org.garik.test.Car),未标记为可忽略(6个已知特性:"马力"、"型号"、"发动机类型"、"年份"、"制造"、"车身样式")在[Source:(BufferedInputStream);行:33,列:24](通过引用链:java.util.ArrayList[3]->org.garik.test.Car[quot;maxLoad"])网址:com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecgnizedPropertyException.java:61)网址:com.fasterxml.jackson.databind.DDeserializationContext.handleUnknownProperty(Deserialization Context.java:1127)网址:com.fasterxml.jackson.databind.deser.StdDeserializer.handleUnknownProperty(StdDeserialize.java:2023)网址:com.fasterxml.jackson.databind.deser.BBeanSerializerBase.handleUnknownProperty(BeanSerializer Base.java:1700)网址:com.fasterxml.jackson.databind.deser.BBeanSerializerBase.handleUnknownManilla(BeanSerializer Base.java:1678)网址:com.fasterxml.jackson.databind.deser.BeanSerializer.vanillaDeserialize(BeanSerializer.java:320)网址:com.fasterxml.jackson.databind.deser.BeanSerializer.deserialize(BeanSerializer.java:177)网址:com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserialize.java:355)网址:com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserialize.java:244)网址:com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserialize.java:28)网址:com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserialization Context.java:323)网址:com.fasterxml.jackson.databind.ObjectMapper.readMapAndClose(ObjectMapper.java:4674)网址:com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3674)网址:org.garik.test.test.main(test.java:21)

如果我将List替换为List,它将毫无错误地完成,但仅为我创建Truck实例,但我需要在此列表中同时创建Car和Truck实例。

您的问题可以通过用JsonTypeInfo注释和JsonSubTypes注释Car超类来解决,如下所示:

@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION, defaultImpl = Car.class)
@JsonSubTypes(@JsonSubTypes.Type(value = Truck.class))
public class Car {/*Car fields */}
public class Truck extends Car {/* specific Truck fields */}
//deserialize to a list containing Car and Truck objects
List<Car> cars = mapper.readValue(json, new TypeReference<List<Car>>() {});

JsonTypeInfo.Id.DEDUCTION意味着jackson试图将json对象反序列化为一个定义的子类型(在这种情况下是唯一的Truck类),并且当与所提出的每个子类型没有完全匹配时,它试图将json对象序列化为默认类(Car类)。

根据我的理解,您只想要Car对象,因此需要在过程中修剪额外的字段。在Car类上方使用此注释可以忽略json字段的额外属性,因为您只需要Car对象。

@JsonIgnoreProperties(ignoreUnknown = true) 
public class Car{
//your fields
}

最新更新