Spring REST Web服务序列化为多种JSON格式 [英] Spring REST webservice serializing to multiple JSON formats

查看:70
本文介绍了Spring REST Web服务序列化为多种JSON格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Spring REST Web服务,该服务基于数据库中的数据填充通用对象,目的是让用户将参数传递给Web服务,以指示他们希望输出的格式根据他们的输入,我们将使用正确的JSONSerializer为他们提供他们想要的东西.

I have a Spring REST web service which populates a generic object based on data we have in a database, the goal is to have the users pass a parameter to the web service to to indicate the format they want the output to be in. Based on their input we will use the correct JSONSerializer to give them what they want.

我已经如下设置了我的Web服务,在spring-ws-servlet.xml中,将我们的公司ObjectMapper设置为由mvc:message-converters使用,我也将其设置在RestController上,以便可以调整ObjectMapper以注册序列化程序.看起来像这样:

I have set up my webservice as follows, in my spring-ws-servlet.xml I have set our company ObjectMapper to be used by the mvc:message-converters, I have also set it on the RestController so that it can adjust the ObjectMapper to register the serializer. It looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean
                class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper" ref="jacksonObjectMapper" />
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <bean id="endpoint" class="org.company.Controller">
        <property name="objectMapper" ref="jacksonObjectMapper" />
    </bean>

    <bean id="jacksonObjectMapper" class="org.company.CompanyObjectMapper" />

</beans>

控制器看起来像这样:

@RestController
public class Controller {

    private ObjectMapper objectMapper;

    @RequestMapping(...)
    public GenericObject getObject(@PathVariables ...) {

        //Get Object from database, just creating an object for example
        GenericObject object = new GenericObject();

        //Based on the user input we will pick out
        //a Serializer that  extends JsonSerializer<GenericObject>
        BaseSerializer serializer = getSerializer();

        //Create a simpleModule and use it to register our serializer
        SimpleModule module = new SimpleModule();
        module.addSerializer(GenericObject.class, serializer);

        //get module and register the serializer
        ObjectMapper mapper = getObjectMapper();            
        mapper.registerModule(module);

        return object;
    }

    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
}

问题在于,当我发布Web应用程序时,第一个查询可以正常工作,如果我指定format = format1,我将获得format1的输出.但是,在那之后,我只能接收format1.我可以指定format = format2,但仍以format1获得输出.我相信问题在于,ObjectMapper仍然从第一个查询向其注册了模块.我已经读到可以通过每次创建一个新的ObjectMapper来避免此问题,但是我不确定如何设置Spring输出JSON时要使用的对象.

The issue is that when I publish my webapp, the first query works correctly, if I specify format=format1, I will get the output in format1. However, after that I can only receive format1. I may specify format=format2, but still get the output in format1. I believe the issue is that the ObjectMapper still has the module registered to it from the first query. I have read that I can avoid this problem by creating a new ObjectMapper every time, but I am not sure how to set that to be used by Spring when it outputs the JSON.

有人可以帮助我想出一个解决方案,或者在每次运行代码时创建一个新的ObjectMapper并将该ObjectMapper设置为Spring rest服务,或者帮助我弄清楚如何注销"已注册的任何模块.在设置最新的所需序列化程序之前在对象映射器上运行?

Could someone help me come up with a solution to either create a new ObjectMapper every time I run the code and set that ObjectMapper to the Spring rest service, or help me figure out how I can "unregister" any modules that are registered on the object mapper before setting the latest desired serializer?

推荐答案

一个想法可能是创建并配置启动时所需的所有映射器作为spring bean.

An idea could be to create and configure all the mappers you need at startup time as a spring beans.

然后创建默认的对象映射器,该对象映射器将用作其他对象映射器的调度程序(或作为后备对象),并且它可能知道当前的http请求. 您可以在该对象映射器中注册所有映射器,并在春季注册该映射器作为默认映射器.

Then create the default object mapper that will work as a dispatcher for other object mappers (or as the fallback one), and it may be aware of the current http request. You can register all the mappers in this object mapper, register this mapper to be used as the default one in spring.

类似这样的东西:

 public class RequestAwareObjectMapper extends ObjectMapper{

    private Map<String, ObjectMapper > mappers = new HashMap<>();

    @Override
    public String writeValueAsString(Object value) throws JsonProcessingException{
        HttpServletRequest req = null;//get request from spring context, if any, this is a managed spring bean it wont be a prorblem
        String param = null; // read the param from the query
        ObjectMapper mapper = mappers.get(param);
        if(mapper == null){
            mapper = this;
        }
        return mapper.writeValueAsString(value);
    }

    public void registerMapper(String key, ObjectMapper mapper){...}
} 

通过这种方式,您不会使用对对象映射器的引用来污染您的控制器,并且可以继续使用@ResponseBody(感谢@RestController)..

in this way you are not going to pollute your controller with references to the object mapper and you can carry on using @ResponseBody (thanks to @RestController)..

我敢肯定,在弹簧流中集成类似的解决方案,有一种更干净的方法可以达到相同的结果,现在无法寻找更好的方法.

I am sure there's a cleaner way to achieve the same result integrating a similar solution in the spring flow, can't look on something better right now.

这篇关于Spring REST Web服务序列化为多种JSON格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆