美文网首页
Jackson 把 json 转为 DBObject

Jackson 把 json 转为 DBObject

作者: Yellowtail | 来源:发表于2019-04-15 17:26 被阅读0次

    需求

    希望通过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

    相关文章

      网友评论

          本文标题:Jackson 把 json 转为 DBObject

          本文链接:https://www.haomeiwen.com/subject/lohpwqtx.html