首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >序列化为多种JSON格式

序列化为多种JSON格式
EN

Stack Overflow用户
提问于 2015-10-23 18:56:08
回答 2查看 1.5K关注 0票数 2

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

我已经按照如下方式设置了我的webservice,在我的spring servlet.xml中,我已经将我们公司的ObjectMapper设置为mvc:消息转换器使用,我还在RestController上设置了它,以便它可以调整ObjectMapper来注册序列化程序。看起来是这样的:

代码语言:javascript
运行
复制
<?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>

控制器如下所示:

代码语言:javascript
运行
复制
@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;
    }
}

问题是,当我发布我的webapp时,第一个查询工作正常,如果我指定了format=format1,我将在format1中获得输出。然而,在那之后,我只能接收format1。我可以指定format=format2,但仍然可以在format1中获得输出。我认为问题在于,ObjectMapper仍然将第一个查询中的模块注册到它。我已经读到,我可以通过每次创建一个新的ObjectMapper来避免这个问题,但是我不知道如何设置它在它输出JSON时被使用。

有人能帮我想出一个解决方案,在我每次运行代码并将该ObjectMapper设置为Spring服务时创建一个新的ObjectMapper,还是帮助我在设置最新的所需序列化程序之前“注销”在对象映射程序上注册的任何模块?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-26 18:09:02

一个想法可以是创建并配置启动时需要的所有映射器,作为spring。

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

可能是这样的:

代码语言:javascript
运行
复制
 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)。

我确信,在弹簧流中集成类似的解决方案,有一种更干净的方法可以实现同样的结果,现在无法看到更好的结果。

票数 2
EN

Stack Overflow用户

发布于 2015-10-26 17:45:34

创建您的customObjectMapper类并使用@Autowire注释自动将其连接到控制器。然后,您可以创建不同的方法来创建不同的格式化对象。

还可以将序列化器作为参数发送。

代码语言:javascript
运行
复制
public class CustomObjectMapper extends ObjectMapper {
    public CustomObjectMapper() {
        super();
        super.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        super.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        ..... etc.....
        super.setDateFormat(df);
    }
    public byte[] generateJsonFormat1(Object value, BaseSerializer serializer) throws IOException, JsonGenerationException, JsonMappingException {
        Hibernate4Module hm = new Hibernate4Module();
        hm.configure(Hibernate4Module.Feature.USE_TRANSIENT_ANNOTATION, false);
        hm.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false);
        .....
        .....
        hm.addSerializer(Object.class, serializer);
        return super.registerModule(hm).writeValueAsBytes(value);
    }

    public byte[] generateJsonFormat2(Object value, BaseSerializer serialiser) throws IOException, JsonGe nerationException, JsonMappingException {
        SimpleModule sm = new SimpleModule();
        sm.addSerializer(Object.class, serialiser);
        return super.registerModule(hm).writeValueAsBytes(value);
    }
}

上面的代码是我自己应用程序中的一个片段。我希望它能给出这个想法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33309557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档