JSON到Java映射参数化/泛型类型

JSON到Java映射参数化/泛型类型,java,json,spring,rest,jackson,Java,Json,Spring,Rest,Jackson,我正在寻求有关处理以下场景的最佳实践的建议 给定一个接受JSON请求的基于Java的Web API,我们需要将JSON对象映射到Java。这个问题是关于Java对象是参数化类型的情况。对于我的特殊情况,我使用Spring和MappingJacksonHttpMessageConverter来进行映射 示例REST服务 @RequestMapping(method = RequestMethod.POST) public void updateContainer(@RequestBody Con

我正在寻求有关处理以下场景的最佳实践的建议

给定一个接受JSON请求的基于Java的Web API,我们需要将JSON对象映射到Java。这个问题是关于Java对象是参数化类型的情况。对于我的特殊情况,我使用Spring和MappingJacksonHttpMessageConverter来进行映射

示例REST服务

@RequestMapping(method = RequestMethod.POST) 
public void updateContainer(@RequestBody Container<?> container) {
    realService.updateContainer(container);
}
@RequestMapping(method=RequestMethod.POST)
public void updateContainer(@RequestBody容器){
更新容器(容器);
}
参数化类型示例

public class Container<T extends ContainerItem> {
      private T containerItem;
      ...
}
公共类容器{
私人集装箱;
...
}
当我调用这个方法时,我会得到一个400错误(错误请求),因为容器的类型在运行时被删除,Jackson不知道如何映射我的containerItem(因为它不知道映射到什么类型)


我实现了一个非常基本的解决方案,我在JSON数据中添加了一个字段,该字段指定containerItem的Java类名,然后添加了一个自定义HttpMessageConverter,它使用这个类名来构造参数化JavaType,然后Jackson ObjectMapper可以使用它来进行映射,但我想知道是否有人有更好的方法来处理这个问题?

一个解决方案是声明一个参数化类型,并使用它作为
@RequestBody的目标,方法如下:

public class MyCustomTypeContainer extends Container<SubContainerItem>  {
..
}

public void updateContainer(@RequestBody MyCustomTypeContainer container) {
    realService.updateContainer(container);
}
公共类MyCustomTypeContainer扩展了容器{
..
}
public void updateContainer(@RequestBody MyCustomTypeContainer){
更新容器(容器);
}
请注意,
MyCustomTypeContainer
必须是参数化类型(完全实现的泛型类型)。这可能意味着您可能必须为每个containerItem类型创建一个子类型


请参阅,以了解与此相同的另一个问题。

解决方案是声明一个参数化类型,并将其用作
@RequestBody
的目标,方法如下:

public class MyCustomTypeContainer extends Container<SubContainerItem>  {
..
}

public void updateContainer(@RequestBody MyCustomTypeContainer container) {
    realService.updateContainer(container);
}
公共类MyCustomTypeContainer扩展了容器{
..
}
public void updateContainer(@RequestBody MyCustomTypeContainer){
更新容器(容器);
}
请注意,
MyCustomTypeContainer
必须是参数化类型(完全实现的泛型类型)。这可能意味着您可能必须为每个containerItem类型创建一个子类型


请参阅,以了解与此相同的另一个问题。

我会避免在服务中暴露JSON中没有任何等价物的结构(如泛型、集合等)。这使得我们很难弄清楚这项服务到底应该如何使用。嗨,millimoose,这是一个公平的观点,但我想我希望这将是一个足够普遍的问题,可能会有一些最佳实践模式或Jackson的语言特征来帮助解决它。例如,JSON没有多态类型的等价物,但Jackson能够通过注释处理这些类型。我会避免在服务中暴露JSON中没有等价物的结构(如泛型、集合等)。这使得我们很难弄清楚这项服务到底应该如何使用。嗨,millimoose,这是一个公平的观点,但我想我希望这将是一个足够普遍的问题,可能会有一些最佳实践模式或Jackson的语言特征来帮助解决它。例如,JSON没有多态类型的等价物,但Jackson能够通过注释处理这些类型。嗨,Biju,如果我只想用一个具体类型的子容器(SubcainerItem)更新容器,这个解决方案就可以了-但如果我也想更新一个装满SubcainerItem2的容器呢?是的,Josh,实际上你的方法听起来也不错。我能想到的一个变化是没有xml中的类名,这看起来不干净,相反,您可以尝试将此信息放在自定义注释中,并使用该注释和创建适当的
JavaType
并在那里进行解组。嗨,Biju,如果我只想用一种具体类型的子容器(SubcainerItem)更新容器,这个解决方案就可以了——但是如果我还想更新一个装满SubcainerItem2的容器呢?是的,Josh,实际上你的方法听起来也不错。我能想到的一个变化是没有xml中的类名,这看起来不干净,相反,您可以尝试将此信息放在自定义注释中,并将该注释与一起使用,以创建适当的
JavaType
,并在那里进行解组。