技术交流28群

服务热线

135-6963-3175

微信服务号

Jackson如何自动转换json为某个子类类型 更新时间 2023-10-29 浏览1842次

方式一:

       在使用 Jackson 库进行 JSON 反序列化时,可以通过使用注解@JsonTypeInfo和@JsonSubTypes来实现自动转换为某个子类类型。

首先,在父类或接口上使用@JsonTypeInfo注解,指定Jackson在反序列化时应该包含类型信息。可以指定use属性为JsonTypeInfo.Id.NAME,并通过property属性指定类型信息的字段名。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
public abstract class Vehicle {
    // 父类字段和方法
}

接下来,在父类或接口上使用@JsonSubTypes注解,指定子类的映射关系。使用@JsonSubTypes.Type注解指定子类的类型和对应的字段值。

@JsonSubTypes({
        @JsonSubTypes.Type(value = Car.class, name = "car"),
        @JsonSubTypes.Type(value = Bike.class, name = "bike")
})
public abstract class Vehicle {
    // 父类字段和方法
}

然后,在子类上使用@JsonTypeName注解,指定该子类对应的字段值。

@JsonTypeName("car")
public class Car extends Vehicle {
    // 子类字段和方法
}
@JsonTypeName("bike")
public class Bike extends Vehicle {
    // 子类字段和方法
}

现在,当使用 Jackson 进行 JSON 反序列化时,它将根据 JSON 数据中指定的类型字段值自动转换为对应的子类类型。

以下是一个示例,展示如何使用 Jackson 进行 JSON 反序列化并自动转换为子类类型:

ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"type\":\"car\",\"color\":\"red\",\"brand\":\"Toyota\"}";
Vehicle vehicle = objectMapper.readValue(json, Vehicle.class);
System.out.println(vehicle.getClass());  // 输出:class Car
System.out.println(vehicle.getColor());  // 输出:red
System.out.println(((Car) vehicle).getBrand());  // 输出:Toyota

在上述示例中,JSON 数据中的type字段指定了子类类型为car,因此 Jackson 自动将其转换为Car类的实例。

请注意,为了使 Jackson 能够正确地进行自动转换,JSON 数据中需要包含类型信息字段,例如type字段。此外,确保您正确配置了 Jackson 的相关设置和注解,以使其能够识别和处理类型信息。


方式二:

除了使用 @JsonTypeInfo 和 @JsonSubTypes 注解外,还有其他方法可以实现 JSON 自动转换为子类类型。

使用 JsonCreator 注解和静态工厂方法:在父类或接口中定义一个静态工厂方法,使用 @JsonCreator 注解标记该方法,并在方法参数中添加一个标识子类类型的字段。在子类中,通过调用父类的静态工厂方法创建子类实例。

public abstract class Vehicle {
    // 父类字段和方法
    @JsonCreator
    public static Vehicle create(@JsonProperty("type") String type) {
        if ("car".equals(type)) {
            return new Car();
        } else if ("bike".equals(type)) {
            return new Bike();
        } else {
            throw new IllegalArgumentException("Invalid vehicle type: " + type);
        }
    }
}
public class Car extends Vehicle {
    // 子类字段和方法
}
public class Bike extends Vehicle {
    // 子类字段和方法
}

2.自定义 JsonDeserializer:创建一个自定义的 JsonDeserializer 类,继承自 com.fasterxml.jackson.databind.JsonDeserializer,并实现 deserialize() 方法。在 deserialize() 方法中根据 JSON 数据中的字段值来判断并创建对应的子类实例。

public class VehicleDeserializer extends JsonDeserializer<Vehicle> {
    @Override
    public Vehicle deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        ObjectCodec codec = jsonParser.getCodec();
        JsonNode node = codec.readTree(jsonParser);
        String type = node.get("type").asText();
        if ("car".equals(type)) {
            return codec.treeToValue(node, Car.class);
        } else if ("bike".equals(type)) {
            return codec.treeToValue(node, Bike.class);
        } else {
            throw new IllegalArgumentException("Invalid vehicle type: " + type);
        }
    }
}

然后,将自定义的 JsonDeserializer 注册到 ObjectMapper 中,以便进行 JSON 反序列化时使用。

ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Vehicle.class, new VehicleDeserializer());
objectMapper.registerModule(module);
String json = "{\"type\":\"car\",\"color\":\"red\",\"brand\":\"Toyota\"}";
Vehicle vehicle = objectMapper.readValue(json, Vehicle.class);

以上是两种不使用 @JsonTypeInfo 和 @JsonSubTypes 注解的方法,通过编程方式实现 JSON 自动转换为子类类型。这些方法可以根据您的需求和代码结构选择适合的方式。