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

fnatzsnv  于 2022-12-18  发布在  其他
关注(0)|答案(2)|浏览(85)

I am receiving from the web service JSON array that contains 2 types of objects - base class and class extending the base (it contains some extra attributes). How can I process it with Jackson that will produce at the end a list of base class in Java. For example, I have a class Car and class Truck which contains attribute maxLoad (and some others) that Car does not have. At the end I need to get List that will contain instances of both Car and Truck. Here is the code:

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
}

And here is the test JSON file and code for test:

[
    {
        "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();
        }
    }
}

When I run this test program, I am getting an exception:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "maxLoad" (class org.garik.test.Car), not marked as ignorable (6 known properties: "horsepower", "model", "engineType", "year", "make", "bodyStyle"]) at [Source: (BufferedInputStream); line: 33, column: 24] (through reference chain: java.util.ArrayList[3]->org.garik.test.Car["maxLoad"]) at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61) at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:1127) at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:2023) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1700) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1678) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:320) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:355) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3674) at org.garik.test.Test.main(Test.java:21)
If I replace List with List it completes without errors, but create me instances of Truck only, but I need in this list instances of both Car and Truck.

mbjcgjjk

mbjcgjjk1#

您的问题可以通过使用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类)。

ryevplcw

ryevplcw2#

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

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

相关问题