您现在的位置是:首页 > 文章详情

Java对MongoDB的ObjectId的序列化问题

日期:2018-08-18点击:350

MongoDB在不特殊指认的情况下,默认的集合主键是“_id”,类型是ObjectId。ObjectId是一个12字节的BSON类型字符串,包含了UNIX时间戳,机器识别码,进程号,计数值信息。机器码用来防止分布式系统生成id时冲突的问题,保证每台机器生成的识别码不同,进程号保证多线程情况下生成的id不同。
ObjectId在java程序中是对象类型,JavaBean中常这样使用:

@Document(collection = "c_userinfo") public class UserInfo{ @Id private ObjectId id; private String name; // getter setter略 } 

此时,如果直接实体类序列化为json,id将被作为对象处理,前段无法将此对象转为字符串,也无法将此id作为唯一标识调用其他数据。

{ id: { "time": 1494233455000, "timestamp": 1494233455, "date": 1494233455000, "new": false, "timeSecond": 1494233455, "inc": -125534200, "machine": -1248386109 } } 

故有时需要将ObjectId的序列化做处理,将ObjectId直接序列化为字符串。
以springmvc为例,在接口返回数据前统一处理序列化问题。自定义类实现ResponseBodyAdvice接口,重写beforeBodyWrite方法,自定义序列化方法。

import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializeConfig; import org.bson.types.ObjectId; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; @ControllerAdvice public class MyResponseBodyAdvice implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { SerializeConfig config = new SerializeConfig(); config.put(ObjectId.class, new ObjectIdJsonSerializer()); return JSONObject.parse(JSON.toJSONString(body, config)); } } 

然后实现一个ObjectIdJsonSerializer

import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.ObjectSerializer; import com.alibaba.fastjson.serializer.SerializeWriter; import org.bson.types.ObjectId; import java.io.IOException; import java.lang.reflect.Type; public class ObjectIdJsonSerializer implements ObjectSerializer { @Override public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,int features) throws IOException { SerializeWriter out = serializer.getWriter(); if (object == null) { serializer.getWriter().writeNull(); return; } out.write("\"" + ((ObjectId) object).toString() + "\""); } } 

这样处理后接口返回的id将变成字符串类型。

{ "id":"5ae078ada0f091000be702b8" } 

同理spring mvc对于Date类型的输出默认为时间戳格式,我们可以自定义输出为格式化字符串,这样可以免去在前端格式化处理。需要在MyResponseBodyAdvice 中注册DateJsonSerializer 。

 import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.ObjectSerializer; import com.alibaba.fastjson.serializer.SerializeWriter; import org.bson.types.ObjectId; import java.io.IOException; import java.lang.reflect.Type; import java.util.Date; public class DateJsonSerializer implements ObjectSerializer { @Override public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,int features) throws IOException { SerializeWriter out = serializer.getWriter(); if (object == null) { serializer.getWriter().writeNull(); return; } out.write("\"" + DateUtil.format(((Date)object),"yyyy-MM-dd: HH:mm:ss") + "\""); } } 
原文链接:https://yq.aliyun.com/articles/633439
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章