【问题标题】:Difference in serialized JSON in case of inheritance in Spring and Javax RS REST APIs在 Spring 和 Javax RS REST API 中继承的情况下,序列化 JSON 的差异
【发布时间】:2019-09-17 03:12:09
【问题描述】:

我有一个使用 Javax.ws.rs 实现的 GET REST API,如下所示

@GET
    @Path("/test")
    @Produces(MediaType.APPLICATION_JSON)
    @JacksonFeatures(serializationEnable = { SerializationFeature.INDENT_OUTPUT })
    @ApiOperation(value="Returns the metadata for the specified attributes.")
    @ApiResponses(value = {
              @ApiResponse(code = 500, message = "Internal Server Error, Please check the logs for more details.")
            })
    public  List<Parent> getTest(@ApiParam(value="", required=false)@RequestParam(value ="name", required = false) String name)
            throws Exception {
        List<Parent> children = new ArrayList<>();
        children.add(new ChildA());
        children.add(new ChildB());
        children.add(new ChildA());
        return children;
    }


    @JsonTypeInfo(
            use = JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.PROPERTY,
            property = "type")
    @JsonSubTypes({
        @JsonSubTypes.Type(value = ChildA.class, name = "childA"),
        @JsonSubTypes.Type(value = ChildB.class, name = "childB"),
        })
    interface Parent extends Serializable{

    }

    class ChildA implements Parent{

    }

    class ChildB implements Parent{

    }

它工作得很好,我得到了这个 API 的以下响应:

[
    {
        "type": "childA"
    },
    {
        "type": "childB"
    },
    {
        "type": "childA"
    }
]

我正在使用 Spring 4.1.2 创建相同的 API。商务舱和服务将保持不变。现在我只是为这个 API 创建一个新的 Spring 控制器:

@RequestMapping(value = "/test",method = RequestMethod.GET, produces=MediaType.APPLICATION_JSON)
    @ApiOperation(value = "data", notes="some note.")
    @ApiResponses(value = {
              @ApiResponse(code = 500, message = "Internal Server Error, Please check the logs for more details.")
            })
    public  List<Parent> getTest(@ApiParam(value="", required=false)@RequestParam(value ="name", required = false) String name)
            throws Exception {

        List<Parent> children = new ArrayList<>();
        children.add(new ChildA());
        children.add(new ChildB());
        children.add(new ChildA());
        return children;
    }

现在这个新 API 返回以下 JSON:

[
    {},
    {},
    {}
]

我知道这是由于 Java 在编译时的类型擦除功能而发生的。 Spring 无法找出 List 的参数化类型,因此无法在序列化 JSON 中添加“类型”。 但是,这如何与旧的 Javax RS API 一起工作,以及如何在不更改返回的 JSON 格式的情况下在新 API 中解决这个问题

【问题讨论】:

    标签: java json spring rest jax-rs


    【解决方案1】:

    这实际上是 Jackson 的一个特性,不依赖于 JAX-RS 或 Spring Boot。

    在您的 Spring Boot 应用程序中,您可以像以前一样使用相同的 @JsonTypeInfo 和 @JsonSubTypes 注释来注释父接口和子类,并且类型推断将像以前一样工作。 Jackson 应该已经包含在您的 Spring Boot 应用程序的依赖项/类路径中(通过父 POM。)

    【讨论】:

    • Parent 和 ChildA 接口/类在这种情况下很常见,因此它们已经被注释了。 Jackson 也包含在 Spring 应用程序中。从旧应用程序序列化时,同一个子类以某种方式具有“类型”,但从 Spring 应用程序序列化时却没有。
    • @IshanRastogi 我从您的示例 (see gist here) 中制作了一个最小的 Spring Boot 控制器,它运行良好,所以问题似乎在应用程序的其他地方,可能与 Spring Boot 本身无关。我还尝试了一个带有 swagger / spring fox 的版本,因为您有 API 注释(以防发生冲突),并且效果也很好。我使用了 Spring Boot 2.1.4-RELEASE,starter web。也许尝试通过从您更完整的应用程序中创建一个类似的最小示例来隔离问题?
    • 是的,看起来 2 个不同的流程存在一些问题。可能是序列化程序版本不同。我没有时间调试它,所以现在我正在使用 ObjectMapper 从 Map 创建 JSON 字符串,它可以从那里正常工作,因为我提供了 Map 键值类型的信息。
    猜你喜欢
    • 2023-03-20
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多