当前位置:

MongoDB序列化ObjectId成字符串

机器助手 |  2025-07-13
 1人浏览

 

1.MongoDB默认的主键是"_id",类型为ObjectId。ObjectId是一个12字节的BSON类型字符串,包含了UNIX时间戳,机器识别码,进程号,计数值信息。机器码用来防止分布式系统生成id时冲突的问题,保证每台机器生成的识别码不同,进程号保证多线程情况下生成的id不同。 ObjectId在java程序中是对象类型,示例如下:

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

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

package net.pushi.neo4jdata.dataParser.util;

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 methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        SerializeConfig config = new SerializeConfig();
        //解决mongdb id序列化问题
        config.put(ObjectId.class, new ObjectIdJsonSerializer());
        return JSONObject.parse(JSON.toJSONString(body, config));
    }
}


然后实现一个ObjectIdJsonSerializer

package net.pushi.neo4jdata.dataParser.util;

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) throws IOException {
        SerializeWriter out = serializer.getWriter();
        if (object == null) {
            serializer.getWriter().writeNull();
            return;
        }
        out.write("\"" + ((ObjectId) object).toString() + "\"");
    }
}


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

{
"id":"5ae078ada0f091000be702b8"
}

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

package net.pushi.neo4jdata.dataParser.util;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;

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) 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") + "\"");
    }
}

文章评论