【问题标题】:Spring @RequestBody for subclass. Alternative to @JsonTypeInfo?子类的 Spring @RequestBody。 @JsonTypeInfo 的替代品?
【发布时间】:2017-11-12 20:37:48
【问题描述】:

努力做到这一点

@RequestMapping
public String helloWorld(@RequestBody Parent interface){
    // do something with interface

}

其中Parent 是一个接口,Child1Child2 是实现。

因为那些是 3rd-party library .class 文件,我不能使用@JsonTypeInfo

这种情况有什么解决方法吗?

【问题讨论】:

  • ObjectMapper 是最好的(杰克逊罐子)。导入 com.fasterxml.jackson.databind.ObjectMapper; @Autowired 私有 ObjectMapper 对象映射器; YourClassName yourObjectname= objectMapper.readValue(JsonString,YourClassName.class);

标签: rest spring-boot jackson


【解决方案1】:

是的,您可以使用 Jackson Mixin 为第三方/不可触摸的类提供杰克逊注释。

https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations

这个例子相当老了,从这里提供,但从我上次实现 MixIn 时看它仍然是正确的,

http://programmerbruce.blogspot.co.uk/2011/05/deserialize-json-with-jackson-into.html

上面的例子5,

{     "animals":
    [
       {"type":"dog","name":"Spike","breed":"mutt",        
       "leash_color":"red"},
       {"type":"cat","name":"Fluffy",
           "favorite_toy":"spider ring"}
     ]
   }


import java.io.File;
import java.util.Collection;

import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.annotate.JsonTypeInfo;
import org.codehaus.jackson.annotate.JsonSubTypes.Type;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setPropertyNamingStrategy(
        new CamelCaseNamingStrategy());
    mapper.getDeserializationConfig().addMixInAnnotations(
        Animal.class, PolymorphicAnimalMixIn.class);
    mapper.getSerializationConfig().addMixInAnnotations(
        Animal.class, PolymorphicAnimalMixIn.class);
    Zoo zoo = 
      mapper.readValue(new File("input_5.json"), Zoo.class);
    System.out.println(mapper.writeValueAsString(zoo));
  }
}

class Zoo
{
  public Collection<Animal> animals;
}

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
@JsonSubTypes({
    @Type(value = Cat.class, name = "cat"),
    @Type(value = Dog.class, name = "dog") })
abstract class PolymorphicAnimalMixIn
{

}

abstract class Animal
{
  public String name;
}

class Dog extends Animal
{
  public String breed;
  public String leashColor;
}

class Cat extends Animal
{
  public String favoriteToy;
}

您可以使用Jackson2ObjectMapperBuilderJackson2ObjectMapperFactoryBean 在 Spring Boot 中注册 MixIn。

可以在此处找到 Spring Boot 世界中的上述工作示例,其中包含验证 Cat/Dog 成功 POST 的测试,例如父类的具体实现。

https://github.com/Flaw101/springbootmixin

【讨论】:

  • 好的,谢谢你的正确方向。但是,我仍在寻找一种在 Spring 上下文中使用 @RequestBody 的方法。
  • @ReuestBody 使用 Jackson 映射到目标类,具体取决于传入的有效负载。如果您将ObjectMapper 设置为使用MixIn,它将起作用。这是做你所要求的正确方法。请参阅baeldung.com/spring-httpmessageconverter-rest,了解有关传入请求如何映射到预期的更多信息。
  • 感谢达伦,我阅读了链接中的说明,但仍然对如何实现这一点感到困惑。它确实提到了创建自定义转换器,但我没有看到任何 MixIn、ObjectMapper 或继承相关的东西。此外,我正在使用没有 XML 配置的 Spring boot,该指南建议我需要一个。您能否提供一个代码示例,因为我更困惑?
  • @JunPark 这是一个你可以克隆的工作示例,我把它从上面的示例中创建并实现到 Spring Boot 中,github.com/Flaw101/springbootmixin 有一个 ControllerTest 发布,一个猫和狗,并被读入一个动物控制器中的对象。
  • 感谢 Darren,我能够根据您提供的指示解决问题。但是,我看到当我将 MixIn 与可实例化的超类一起使用时,它优先于子类。有没有办法强制 MixIn 注释优先?
猜你喜欢
  • 2015-05-15
  • 2023-03-31
  • 2019-04-04
  • 2011-09-23
  • 1970-01-01
  • 2019-06-07
  • 1970-01-01
  • 2020-05-01
  • 1970-01-01
相关资源
最近更新 更多