Jackson 把 json 转为 DBObject

需求

希望通过Jackson 把 json 转为 DBObject
use jackson, convert json string to DBObject

尝试

刚开始实现这个功能的时候,没有想到这里有坑,直接写的代码,如下

public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        
        DBObject dbObject = new BasicDBObject("h", "a");
        String json = objectMapper.writeValueAsString(dbObject);
        
        System.out.println(json);
        
        DBObject readValue = objectMapper.readValue(json, DBObject.class);
        
        System.out.println(readValue);
    }

输出为

{"h":"a"}
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.mongodb.DBObject, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
 at [Source: {"h":"a"}; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:892)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:139)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
    at xxx.AsyncMessageHelper.main(AsyncMessageHelper.java:91)

可以看到 序列化 这个过程是没有问题的,正常输出 {"h":"a"}

但是 反序列化出了问题,抛了异常

看异常信息,大概问题是因为 DBObject 是一个接口,所以 Jackson 在实例化的时候,不知道该用哪个实现类去实例化

网上搜了很多文章,最后找到了一种可行的方案(也许还有其它的方案)

code

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;

public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        
        DBObject dbObject = new BasicDBObject("h", "a");
        String json = objectMapper.writeValueAsString(dbObject);
        
        System.out.println(json);
        
        SimpleModule module = new SimpleModule();
        module.addDeserializer(DBObject.class, new DBObjectDeserializer(DBObject.class));
        objectMapper.registerModule(module);
        
        DBObject readValue = objectMapper.readValue(json, DBObject.class);
        
        System.out.println(readValue);
    }
    
    public static class DBObjectDeserializer extends StdDeserializer<DBObject> {
        protected DBObjectDeserializer(Class<?> vc) {
            super(vc);
        }

        @Override
        public DBObject deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            String string = p.readValueAsTree().toString();
            
            return (DBObject) JSON.parse(string);
        }
        
    }

输出

{"h":"a"}
{ "h" : "a"}

原理

首先,写了个DBObjectDeserializer,实现了标准反序列化接口
在具体的反序列化方法deserialize 中,使用了 MongoDB 官方的 JSON 工具类(这个类的方法可以正常反序列化DBObject

其次,向我们的 ObjectMapper 注册了一个 SimpleModule
这个 module 有一个反序列化实例,就是我们刚刚写的 DBObjectDeserializer

参考

https://www.baeldung.com/jackson-custom-serialization

https://stackoverflow.com/a/12261133

https://stackoverflow.com/questions/41001302/jackson-deserializer-for-one-custom-field

https://stackoverflow.com/a/16825934

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容