上周公司让我做MongoDB的Document与json自定义相互转换工作,具体就是
1.将后台的Document直接返回给前台,前台接收到的是json数据,而且里面的ObjectId是字符串的形式:
“_id”:{ “$oid”: “598da5dd3888f020b164b25f” } 转成 “_id”:”598da5dd3888f020b164b25f”
2.前台传入后台的处理和上面相反:
_id”:”598da5dd3888f020b164b25f” 转成 “_id”:{ “$oid”: “598da5dd3888f020b164b25f” }
其他都不变。
举例来讲:
前台传入的json字符串:
{“name”:”张三111111”,”_id”:”598da5dd3888f020b164b25f”,”position”:”辽宁”,”age”:28}
后台controller中:
@RequestMapping(value="/findone")
public Document findOne(@RequestBody Document document) throws Exception{
System.out.println("传进来的Document-->"+document);
System.out.println("传进来的Document.toJson--->"+document.toJson());
String collection = "hos_user_info";
String id = "598da5dd3888f020b164b25f";
Document doc = service.queryById(collection, id);
System.out.println("findOne(),doc.toString---->"+doc);
System.out.println("findOne(),doc.toJson()---->"+doc.toJson());
return doc;
}
直接用Document,接收入参,直接返回Document对象。同时前台收到的是json字符串,而且id是字符串形式。
所以,此处就需要自定义json 的转换器了:
1.自定义类DocumentHttpMessageConverter,继承AbstractHttpMessageConverter。
具体代码:
public class DocumentHttpMessageConverter extends AbstractHttpMessageConverter<Document> {
private Logger logger = LoggerFactory.getLogger(DocumentHttpMessageConverter.class);
public DocumentHttpMessageConverter() {
super(new MediaType("application", "json", Charset.forName("UTF-8"))); //自定义的类型:application/json
}
@Override
protected boolean supports(Class<?> clazz) {
return Document.class.isAssignableFrom(clazz); //只支持Document对象
}
/**
* @Author
* @Date 9:58 八月 24 0024
* @Description: 读取请求数据,构造Document对象,将输入的json(ObjectId以字符串形式)中"_id": "59915afa19191fcffc24a1d9" 改成: "_id": { "$oid": "59915afa19191fcffc24a1d9" }格式,以用于转化成Document对象
*/
@Override
protected Document readInternal(Class<? extends Document> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
String inputjson = StreamUtils.copyToString(inputMessage.getBody(), Charset.forName("UTF-8"));
System.out.println("inputstream"+inputjson);
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(ObjectId.class, new ObjectIdDeserializer());
mapper.registerModule(module);
ObjectId oid = mapper.readValue(inputjson, ObjectId.class);
inputjson = inputjson.replace("\"" + oid.toString() + "\"", "{ \"$oid\": \"" + oid.toString() + "\" }");
System.out.println("输入数据自动转换>"+inputjson);
return Document.parse(inputjson);
}
/**
* @Author
* @Date 9:59 八月 24 0024
* @Description: 将Document转化成json(ObjectId以字符串形式)字符串,输出。去掉了ObjectId,由"_id" : ObjectId("598d5bb7791c00bbf615977a")改成了:"_id":"598d5bb7791c00bbf615977a"
*/
@Override
protected void writeInternal(Document document, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> docmap = new HashMap<String, Object>(16);
Iterator itdoc = document.entrySet().iterator();
while (itdoc.hasNext()) {
Document.Entry entry = (Document.Entry) itdoc.next();
Object value = entry.getValue();
if (value instanceof ObjectId) {
value = value.toString();
}
docmap.put((String) entry.getKey(), value);
}
String out = mapper.writeValueAsString(docmap);
System.out.println("writeInternal,78lines,out-->"+out);
outputMessage.getBody().write(out.getBytes("UTF-8"));
}
}
2.自定义ObjectId返序列化类ObjectIdDeserializer,继承JsonDeserializer
public class ObjectIdDeserializer extends JsonDeserializer<ObjectId> {
@Override
public ObjectId deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree(p);
String oid = node.get("_id").asText();
System.out.println("反序列化:》"+oid);
return new ObjectId(oid);
}
}
3.配置spring文件:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<!-- 增加自定义处理MongoDB 的Document 与 普通Json字符串的转换 -->
<bean class="com.converter.DocumentHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
这里要特别注意下:
register-defaults=”false” 这个不用配置应该也可以,具体看项目