MongoDB的ObjectId的序列化问题

MongoDB默认使用ObjectId作为主键,它包含时间戳、机器码等信息。在Java中,ObjectId序列化为json时会导致前端处理困难。解决办法是在Spring MVC中利用ResponseBodyAdvice自定义序列化,将ObjectId转换为字符串,确保接口返回的id是可读的字符串类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


ObjectId在java程序中是对象类型,JavaBean中常这样使用:

public class BaseVo {
    @Id
    private ObjectId id;

    private Integer status;

    private Long inDate;

    private Long reDate;

    // 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方法,自定义序列化方法。

@ControllerAdvice
public class myResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // TODO Auto-generated method stub
        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.parseObject(JSON.toJSONString(body, config));
    }
}
public class ObjectIdJsonSerializer implements ObjectSerializer {
    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType) throws IOException {
        SerializeWriter out = serializer.getWriter();
        if (object == null) {
            serializer.getWriter().writeNull();
            return;
        }
        out.write("\"" + ((ObjectId) object).toString() + "\"");
    }
}

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

原创团队
【总监】十二春秋之,3483099@qq.com;
【Master】zelo,616701261@qq.com;【运营】狼行天下,897221533@qq.com;
【产品设计】流浪猫,364994559@qq.com;【体验设计】兜兜,2435632247@qq.com;
【iOS】淘码小工,492395860@qq.com;iMcG33K,imcg33k@gmail.com;
【Android】人猿居士,1059604515@qq.com;思路的顿悟,1217022114@qq.com;
【Java】首席工程师MR_W,feixue300@qq.com;【测试】土镜问道,847071279@qq.com;
【数据】喜乐多,42151960@qq.com;【安全】保密,你懂的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值