You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebSocket中如何正确将DTO的ObjectId字段映射为String类型

Spring WebSocket 中 ObjectId 序列化为十六进制字符串配置方案

Spring WebSocket 默认使用 Jackson 做 JSON 序列化,ObjectId 被输出为包含时间戳、机器标识等属性的结构化对象,是因为默认序列化器未直接调用toString()方法输出单值,以下是两种可直接使用的实现方式:

  • 全局配置:一次配置后所有ObjectId字段自动按字符串格式序列化/反序列化,适合项目中大量使用ObjectId的场景
  • 单字段注解配置:仅对指定字段生效,适合只有少量字段需要转换的场景

全局配置实现步骤

1. 编写自定义序列化与反序列化器

序列化器负责将ObjectId转为十六进制字符串输出:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.bson.types.ObjectId;
import java.io.IOException;

public class ObjectIdJsonSerializer extends JsonSerializer<ObjectId> {
    @Override
    public void serialize(ObjectId objectId, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(objectId.toHexString());
    }
}

反序列化器负责接收前端传入的十六进制字符串,转回ObjectId类型:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.bson.types.ObjectId;
import java.io.IOException;

public class ObjectIdJsonDeserializer extends JsonDeserializer<ObjectId> {
    @Override
    public ObjectId deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        return new ObjectId(jsonParser.getText());
    }
}

这里用toHexString()和直接调用toString()效果一致,都是输出标准的24位ObjectId十六进制字符串。

2. 注册到WebSocket消息转换器

注意Spring WebSocket不会复用Spring MVC的Jackson配置,需要单独给WebSocket的消息转换器注册自定义模块:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.bson.types.ObjectId;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import java.util.List;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        MappingJackson2MessageConverter jacksonConverter = new MappingJackson2MessageConverter();
        ObjectMapper objectMapper = jacksonConverter.getObjectMapper();

        SimpleModule objectIdModule = new SimpleModule();
        objectIdModule.addSerializer(ObjectId.class, new ObjectIdJsonSerializer());
        objectIdModule.addDeserializer(ObjectId.class, new ObjectIdJsonDeserializer());
        objectMapper.registerModule(objectIdModule);

        messageConverters.add(jacksonConverter);
        // 返回false表示不加载默认消息转换器,避免默认的ObjectId序列化逻辑覆盖自定义配置
        return false;
    }
}

单字段注解实现

如果不需要全局生效,直接在DTO对应字段上加Jackson注解指定序列化器即可,不需要改全局配置:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.bson.types.ObjectId;

@AllArgsConstructor
@Data
public class MessageDto {
    @JsonSerialize(using = ToStringSerializer.class)
    @JsonDeserialize(using = ObjectIdJsonDeserializer.class)
    private ObjectId messageId;
    @JsonSerialize(using = ToStringSerializer.class)
    @JsonDeserialize(using = ObjectIdJsonDeserializer.class)
    private ObjectId chatId;
}

注意:@JsonSerialize(using = ToStringSerializer.class)仅解决返回时的序列化问题,如果需要接收前端传入的ObjectId字符串参数,必须补充@JsonDeserialize注解指定反序列化器,否则会报类型不匹配错误。

验证结果

配置完成后,接口返回的JSON结构会符合预期:

{
  "messageId": "62790c02513ad11442eec6d7",
  "chatId": "6279125f7b23af2d7c9a1b32"
}

不会再出现嵌套的timestamp、counter、machineIdentifier等属性结构。

内容的提问来源于stack exchange,提问作者Maksym Gaiduchek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 21:27:18