【问题标题】:Object Mapper mapping for a particular class during http callshttp 调用期间特定类的对象映射器映射
【发布时间】:2016-11-30 18:57:56
【问题描述】:

有没有办法通过注解为特定类添加 ObjectMapper。

@JsonRootName("employee")
public class Sample implements Serializable{
    private String name;
    private String id;
    // Getters and setters 
}

在 RestController 中,我有 RequestMapping 和类似的方法:-

 @ResponseBody
 public Sample (@RequestBody Sample sample){
 //some logic
 return sample;
}

我对此的输入有效负载将类似于

    {
      "employee":{
            "name":"abcd",
            "id":"1234"
        }
    }

我想要的输出是

{
    "name":"abcd",
    "id":"1234"
}

1)有没有办法可以使用同一个类来实现输入和输出。

2) 我在类的顶部添加了@JsonRootName,这需要 ObjectMapper 的序列化功能启用到 WRAP_ROOT_VALUE,例如:-

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); 

可以将其添加到仅反映在此类中的位置。

【问题讨论】:

    标签: java spring http spring-mvc jackson


    【解决方案1】:

    也许只是保留默认的序列化行为?然后,在反序列化时你仍然会拉出“员工”包装器,但在序列化时你会在没有包装器的情况下编写它。

    ObjectMapper mapper = new ObjectMapper();
    //mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
    mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); 
    

    有了你的输入,我得到了想要的序列化输出:

    {"name":"abcd","id":"1234"}
    

    编辑

    至于将这段代码放在哪里,我建议使用带有静态方法的单例或类来处理您的(反)序列化。您可以有两个不同的映射器,而不是执行“正常”或“包装”行为。以下是静态方法方法的概述:

    public class SerializationUtil {
        private static ObjectMapper normalObjectMapper;
        private static ObjectMapper wrappedObjectMapper;
    
        static {
            /* configure different (de)serialization strategies */
            normalObjectMapper = new ObjectMapper();
            wrappedObjectMapper = new ObjectMapper();
            wrappedObjectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
            wrappedObjectMapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
        }
    
        public static <T> T normalDeserialize(String json, Class<T> clazz) throws Exception {
            return normalObjectMapper.readValue(json, clazz);
        }
    
        public static String normalSerialize(Object bean) throws Exception {
            return normalObjectMapper.writeValueAsString(bean);
        }
    
        public static <T> T deserializeWrappedObject(String json, Class<T> clazz) throws Exception {
            return wrappedObjectMapper.readValue(json, clazz);
        }
    
        public static String serializeWrappedObject(Object bean) throws Exception {
            return wrappedObjectMapper.writeValueAsString(bean);
        }
    }
    

    这种方法的好处是它允许调用者决定序列化行为。因此,如果您的代码的某些部分需要以不同方式处理,您可以调用另一个方法。请注意,包装/展开都已启用。所以为了得到你想要的行为,你可以这样调用这些方法:

    public static void main(String[] args) {
        Bean bean = SerializationUtil.deserializeWrappedObject(jsonInput, Bean.class);
        String jsonOutput = SerializationUtil.normalSerialize(bean);
    }
    

    如果这对您没有吸引力,您也可以检测特殊情况并在同一个方法调用中处理它:

    public static <T> T deserialize(String json, Class<T> clazz) throws Exception {
        if (clazz instanceof Bean) {
            return wrappedObjectMapper.readValue(json, clazz);
        } else {
            return normalObjectMapper.readValue(json, clazz);
        }
    }
    

    【讨论】:

    • 我的问题还询问将这个对象映射器代码放在哪里,因为如果我创建一个 bean,它将应用于整个项目。但我只想在这个 Sample 类中进行反序列化,而不是在任何其他类中。
    • @sunder 我更新了我的答案。这就是你要找的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    • 2019-09-19
    • 1970-01-01
    • 2023-03-18
    • 2021-02-17
    • 1970-01-01
    相关资源
    最近更新 更多