登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  Golang >  Go教程

jsonv2为字段设置自定义格式

来源:17golang原创

时间:2026-11-15 03:08:22 491浏览 收藏

在 Go 1.25 的 JSON v2 实验接口中,可在结构体的 json 标签中加入 format:值,为支持该格式的字段指定表示方式。例如时间字段使用 format:'2006-01-02' 表达日期字符串。格式由字段类型解释,不能把任意格式名套到任意类型上。

官方地址:https://pkg.go.dev/encoding/json/v2@go1.25.0

本文示例明确针对 Go 1.25 实验接口。它不受 Go 1 兼容性承诺保护;最新包文档的标签列表已经与这个版本不同。维护其他版本项目时,应打开对应版本文档,不能只复制旧实验标签。这里的 jsonv2 是示例导入别名,实际路径为 encoding/json/v2。

固定工具链,让输入与格式约定一致

假设要保存一份日报:业务层提供一个日期,JSON 文件只需要年、月、日。先决定传输数据的含义,再决定字段表示。日期不携带完整时刻信息,如果业务需要精确到秒的事件时间,就不应为了页面好看而在存储时删掉时分秒。

Go 1.25 的该实验包需要构建时设置 GOEXPERIMENT=jsonv2。请使用已经安装的 Go 1.25 工具链;下面命令本身不会把其他版本自动切换为 Go 1.25。

# 在 Go 1.25 工具链中为当前命令启用 JSON v2 实验。
GOEXPERIMENT=jsonv2 go run main.go

把项目的工具链版本和实验变量写入开发说明,团队成员与构建环境使用同一约定。不要因为标签能够写进源码,就推断当前实际调用的编码器一定理解它。

把格式绑定到传输字段

本例的 Report 只有 Name 与 Day 两个字段。Day 在 Go 内部仍是 time.Time;标签约束的是其 JSON 表示。JSON 字段名 day 与日期布局分别承担命名和格式职责,不要混写。

package main

import (
    jsonv2 "encoding/json/v2"
    "fmt"
    "log"
    "time"
)

// Report 是传输对象;日期格式只属于这个字段的 JSON 表示。
type Report struct {
    Name string `json:"name"`
    Day time.Time `json:"day,format:'2006-01-02'"`
}

func main() {
    // 使用零时分秒的 UTC 日期,避免把日期字段误当作完整时间戳。
    source := Report{
        Name: "inventory",
        Day: time.Date(2026, 11, 15, 0, 0, 0, 0, time.UTC),
    }
    data, err := jsonv2.Marshal(source)
    if err != nil {
        log.Fatal(err) // 编码失败时不保存不完整结果。
    }
    fmt.Println(string(data))

    // 用相同传输结构读取,不能随意换成默认时间格式字段。
    var restored Report
    if err := jsonv2.Unmarshal(data, &restored); err != nil {
        log.Fatal(err)
    }
    fmt.Println(restored.Day.Format("2006-01-02"))
}

按上述输入与格式约定,JSON 中的 day 应表达字符串“2026-11-15”,最后一行打印同一日期。这是示例的预期含义,不是本文的运行记录。读者可以在自己的 Go 1.25 环境中观察编码结果与返回错误。

Report字段类型与JSON格式标签之间的静态关系
静态结构图:Report 包含 Name 和 Day;Day 的类型与日期布局共同限定其传输表示。

保存表示时,也保留读取约定

将 JSON 保存到文件或交给接口消费者后,日期布局就成为双方约定的一部分。读取端应使用对应的字段模型和版本。示例里用同一个 Report 解码,目的是把往返转换的配置放在同一处,降低两端各写一份规则的维护成本。

业务内部可以保留更完整的数据对象,在输出前转换为传输对象。这样同一份数据用于日志、页面和交换文件时,能够分别选择需要的表示。若原始值包含业务时区与时间,请明确日期按哪个时区计算,再构造日期传输字段;仅保存日期无法还原原始完整时刻。

层面本例对象维护重点
业务含义日报所属日期先确定日期如何划分
Go 传输模型Report.Day字段类型与布局配套
交换表示JSON 的 day 字符串消费者知道它是日期
读取模型restored Report与写入约定对应
日报日期与传输模型及读取模型的静态边界
静态关系图:业务日期、传输字段和读取模型分属不同边界;JSON 表示不等于完整业务时间信息。

遇到错误时,先缩小到一个字段

如果格式设置未达到预期,先确认工具链版本、实验开关和导入路径,再把结构体缩小为单个时间字段。不要同时修改字段类型、格式和输入值,否则很难知道是哪一处改变了表现。

所有编码与解码调用都应处理返回错误。编码失败后不要把返回内容直接作为成功文件保存;解码失败后,也不要把目标结构中的部分数据直接提交给业务处理。错误文案可能随实验版本变化,业务逻辑不宜依赖整段错误字符串。

需要迁移历史文件时,先区分旧文件使用的日期约定,再确定读取模型。不要通过覆盖旧文件来“试格式”;可写出新文件并保留原数据,待消费端完成迁移后再按项目保留策略清理。这里不要求为每种格式增加全局自定义编码方法:先解决当前字段的表示,再判断是否确实需要更复杂的类型级扩展。

常见问题

format 能用来控制缩进吗?本例讨论字段值的语义表示。缩进与换行属于 JSON 文本的排版问题,不能用日期布局代替。

可以写成 yyyy-MM-dd 吗?本例使用 Go 时间布局的参考日期写法“2006-01-02”。不要把其他语言的日期占位符直接搬进来。

这个标签会改变 time.Time 本身吗?不会把字段类型改成字符串。它描述该版本编码器如何表示字段;领域数据与传输数据仍需分别设计。

为什么不直接推荐所有项目切换?这是限定版本的实验接口示例。已有项目应按工具链与接口兼容需求决定,不应把某个旧实验标签当成稳定迁移承诺。

参考:Go 1.25 JSON v2 字段格式文档、Go 官方 JSON 实验接口说明。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>