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

Go语言中将SQL Server查询结果序列化为目标JSON格式的问题

解决Go中sql.NullXXX类型JSON序列化格式问题

问题背景

从SQL Server的testGo表查询数据并映射到TrnVmSeries结构体后,使用标准库json.Marshal序列化时,sql.NullString、sql.NullBool等类型会输出包含Valid和对应值的嵌套结构,不符合预期的扁平化格式(有效值输出实际值,无效值输出null)。

当前结构体定义:

type TrnVmSeries struct {
    VmCode   sql.NullString
    IsHidden sql.NullBool
    Cores    sql.NullInt32
    Ram      sql.NullFloat64
}

当前序列化输出:

[
{
"VmCode": {
"String":"",
"Valid":false
},
"IsHidden":{
"Bool":false,
"Valid":true
},
"Cores":{
"Int32":0,
"Valid":true
},
"Ram":
{
"Float64":10,
"Valid":true
}
}
]

预期输出:

[ { "VmCode": null, "IsHidden": false, "Cores": 0, "Ram": 10 } ]

解决方案:实现自定义JSON序列化方法

给TrnVmSeries结构体实现json.Marshaler接口,手动处理每个sql.NullXXX字段的序列化逻辑:

方式一:使用匿名结构体覆盖字段

import (
    "database/sql"
    "encoding/json"
)

type TrnVmSeries struct {
    VmCode   sql.NullString
    IsHidden sql.NullBool
    Cores    sql.NullInt32
    Ram      sql.NullFloat64
}

// MarshalJSON 自定义序列化方法
func (t TrnVmSeries) MarshalJSON() ([]byte, error) {
    type Alias TrnVmSeries
    return json.Marshal(&struct {
        VmCode interface{} `json:"VmCode"`
        Alias
    }{
        VmCode:   t.VmCode.Valid ? t.VmCode.String : nil,
        Alias:    (Alias)(t),
        IsHidden: t.IsHidden.Bool,
        Cores:    t.Cores.Int32,
        Ram:      t.Ram.Float64,
    })
}

方式二:使用临时Map构建输出

func (t TrnVmSeries) MarshalJSON() ([]byte, error) {
    data := make(map[string]interface{})
    
    if t.VmCode.Valid {
        data["VmCode"] = t.VmCode.String
    } else {
        data["VmCode"] = nil
    }
    
    data["IsHidden"] = t.IsHidden.Bool
    data["Cores"] = t.Cores.Int32
    data["Ram"] = t.Ram.Float64
    
    return json.Marshal(data)
}

代码说明

  • 实现MarshalJSON方法后,调用json.Marshal(resObj)时会自动触发自定义序列化逻辑
  • 对于sql.NullString,当Valid为false时输出null,否则输出实际字符串
  • 对于sql.NullBool、sql.NullInt32、sql.NullFloat64,直接输出对应基础类型值(符合预期示例中的格式)

补充:反序列化支持(可选)

如果后续需要将JSON反序列化回TrnVmSeries结构体,需实现json.Unmarshaler接口:

func (t *TrnVmSeries) UnmarshalJSON(data []byte) error {
    type Alias TrnVmSeries
    aux := &struct {
        VmCode *string `json:"VmCode"`
        *Alias
    }{
        Alias: (*Alias)(t),
    }
    
    if err := json.Unmarshal(data, aux); err != nil {
        return err
    }
    
    if aux.VmCode != nil {
        t.VmCode.String = *aux.VmCode
        t.VmCode.Valid = true
    } else {
        t.VmCode.Valid = false
    }
    
    t.IsHidden.Valid = true
    t.Cores.Valid = true
    t.Ram.Valid = true
    
    return nil
}

验证效果

修改结构体后,原ReadSqlData函数无需改动,执行后会输出预期的扁平化JSON格式。

内容的提问来源于stack exchange,提问作者ARUNKUMAR RAVI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:33:28