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

如何在Golang中实现枚举与Bson&Json映射并存入MongoDB

Go中实现MongoDB与请求兼容的字符串枚举字段

1. 定义自定义枚举类型

在enums包下声明基于string的枚举类型和常量,既满足MongoDB字符串存储要求,又能通过类型约束限定取值:

package enums

type StudentType string

const (
	StudentTypePaid     StudentType = "PAID"
	StudentTypeUnpaid   StudentType = "UNPAID"
	StudentTypeInactive StudentType = "INACTIVE"
)

2. 实现有效值校验逻辑

维护合法值集合,用于快速校验输入或数据库读取的字段是否合规:

var validStudentTypes = map[StudentType]bool{
	StudentTypePaid:     true,
	StudentTypeUnpaid:   true,
	StudentTypeInactive: true,
}

// IsValidStudentType 校验StudentType是否为合法枚举值
func IsValidStudentType(t StudentType) bool {
	return validStudentTypes[t]
}

3. 处理JSON序列化/反序列化(请求校验)

实现json.Unmarshaler接口,确保接收HTTP请求时自动校验枚举值,非法值直接返回错误:

import "encoding/json"
import "fmt"

func (t *StudentType) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	validType := StudentType(s)
	if !IsValidStudentType(validType) {
		return fmt.Errorf("invalid studentType: %s, allowed values are PAID, UNPAID, INACTIVE", s)
	}
	*t = validType
	return nil
}

// 可选:实现MarshalJSON确保输出为标准字符串
func (t StudentType) MarshalJSON() ([]byte, error) {
	return json.Marshal(string(t))
}

4. 处理BSON序列化/反序列化(MongoDB兼容)

实现bson.Unmarshaler和bson.Marshaler接口,确保MongoDB读写时自动校验字段值,避免脏数据:

import "go.mongodb.org/mongo-driver/bson"

func (t *StudentType) UnmarshalBSON(data []byte) error {
	var s string
	if err := bson.Unmarshal(data, &s); err != nil {
		return err
	}
	validType := StudentType(s)
	if !IsValidStudentType(validType) {
		return fmt.Errorf("invalid studentType stored in DB: %s", s)
	}
	*t = validType
	return nil
}

func (t StudentType) MarshalBSON() ([]byte, error) {
	return bson.Marshal(string(t))
}

5. 结构体使用与枚举操作

现在你的studentModel可以直接使用该枚举类型,并且在任何场景下都能像原生枚举一样操作:

type studentModel struct {
	StudentType enums.StudentType `bson:"studentType,omitempty" json:"studentType,omitempty"`
	StudentId   int64             `bson:"studentId,omitempty" json:"studentId,omitempty"`
}

// 示例:赋值、比较、打印
func demo() {
	// 用枚举常量直接赋值
	stu := studentModel{
		StudentType: enums.StudentTypePaid,
		StudentId:   12345,
	}

	// 枚举值比较
	if stu.StudentType == enums.StudentTypeUnpaid {
		// 执行对应逻辑
	}

	// 打印枚举值(默认转为字符串,也可自定义String方法)
	println(stu.StudentType) // 输出 "PAID"
}

可选:实现String方法

为了让枚举值的字符串转换更直观,可以补充String()方法:

func (t StudentType) String() string {
	return string(t)
}

这套方案完全满足需求:

  • MongoDB存储的是字符串类型;
  • 请求接收和数据库读写都会自动校验枚举值合法性;
  • 结构体字段可直接用枚举常量赋值、比较,完全当作枚举使用。

内容的提问来源于stack exchange,提问作者Prayansh Dhariwal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:45:57