jackson Java:在json中使用“@class”将json反序列化为rest模板中的对象-SpringBoot

icomxhvb  于 2022-11-08  发布在  Java
关注(0)|答案(2)|浏览(211)

我必须示例化一个类,它使用@class中的信息从JSON扩展抽象类,如下所示。

"name": {
  "health": "xxx",
  "animal": {
    "_class": "com.example.Dog",
    "height" : "20"
    "color" : "white"
  }
},

这里的抽象类是animal,dog扩展了animal类。所以使用@class中的信息,我们可以直接示例化dog。这也是我在restTemplate中得到的响应

ResponseEntity<List<SomeListName>> response = restTemplate.exchange("http://10.150.15.172:8080/agencies", HttpMethod.GET, request, responseType);

执行此行时出现以下错误。由于POJO类是自动生成的,因此无法使用**@JsonTypeInfo**之类的注解
我正在使用Sping Boot 和Maven。此错误出现在控制台中。
无法读取JSON:无法构造“MyPOJO”的示例,问题:抽象类型需要Map到具体类型,具有自定义反序列化程序,或者使用其他类型信息进行示例化

wbrvyc0a

wbrvyc0a1#

通过遵循MixIn's,您可以使用@JsonTypeInfo注解,而不管生成类的事实
“混合注解为”:一种将注解与类相关联而不修改(目标)类本身的方法。
也就是说,您可以:
定义混合类(或接口)的注解将与目标类(或接口)一起使用,以便看起来目标类具有混合类所具有的所有注解(用于配置序列化/反序列化)
因此,您可以编写AnimalMixIn类,类似于

@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "_class")  
@JsonSubTypes({  
    @Type(value = Cat.class, name = "com.example.Cat"),  
    @Type(value = Dog.class, name = "com.example.Dog") })  
abstract class AnimalMixIn  
{  

}

和配置反序列化程序

ObjectMapper mapper = new ObjectMapper();  
    mapper.getDeserializationConfig().addMixInAnnotations(  
    Animal.class, AnimalMixIn.class);

因为您使用的是Sping Boot ,所以可以查看下面的博客文章,了解如何为使用MixIns定制ObjectMapper,Customizing theJacksonObject Mapper,特别注意Jackson2ObjectMapperBuilder的mixIn方法
RestTemplate中使用自定义的ObjectMapper应通过转换器进行设置,如下所示

RestTemplate restTemplate = new RestTemplate();
    List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
    MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter();
    jsonMessageConverter.setObjectMapper(objectMapper);
    messageConverters.add(jsonMessageConverter);
    restTemplate.setMessageConverters(messageConverters);
    return restTemplate;
j9per5c4

j9per5c42#

只是作为@主子奴的回答的补充,他说
您可以自定义ObjectMapper以使用MixIn。自定义Jackson对象Map器,请特别注意Jackson 2 ObjectMapper Builder的mixIn方法
但他没有为RestTemplate定义ObjectMapper。下面是他的回答如何帮助我得出完整的答案。

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.addMixIn(Target.class, MixinClass.class)
    .setVisibility(VisibilityChecker.Std.defaultInstance()
        .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
        .withGetterVisibility(JsonAutoDetect.Visibility.ANY)
        .withSetterVisibility(JsonAutoDetect.Visibility.ANY)
        .withCreatorVisibility(JsonAutoDetect.Visibility.ANY)
    );
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter();
jsonMessageConverter.setObjectMapper(objectMapper);
messageConverters.add(jsonMessageConverter);
restTemplate.setMessageConverters(messageConverters);
MyResponse response =
    restTemplate.exchange(request, new ParameterizedTypeReference<MyResponse>() {
    }).getBody();

相关问题