Golang中Json标签的使用与解析指南

Golang中Json标签的使用与解析指南 在哪些场景下会使用字符串标签?我参考了一篇帖子并尝试相应地使用它,但失败了。 我留下我参考的帖子链接:

Ukiah Smith Ukiah Smith

Go: Marshal and Unmarshal JSON with time and URL data

使用 Go json 包中的编组接口来控制 JSON 中的复杂数据类型。

我的实现方式: https://play.golang.org/p/IJrbAlSuuUU

感谢您的帮助。


更多关于Golang中Json标签的使用与解析指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

为了在使用 string 标签时能够解析,你需要将 JSON 中的值用字符串包裹起来:

	msg := `{
		"id": "1",
		"name": "hello",
		"val": "789.33"
	}`

来自文档:

“string” 选项表示一个字段在 JSON 编码的字符串内部以 JSON 形式存储。它仅适用于字符串、浮点数、整数或布尔类型的字段。这种额外的编码级别有时在与 JavaScript 程序通信时使用:

更多关于Golang中Json标签的使用与解析指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中,字符串标签(string tag)主要用于控制特定类型在JSON序列化/反序列化时的行为。以下是常见使用场景和示例:

1. 时间类型格式化

type Event struct {
    Timestamp time.Time `json:"timestamp,string"` // 序列化为JSON字符串
    Name      string    `json:"name"`
}

func main() {
    event := Event{
        Timestamp: time.Now(),
        Name:      "Meeting",
    }
    
    // 序列化:时间戳变为字符串格式
    data, _ := json.Marshal(event)
    fmt.Println(string(data))
    // 输出: {"timestamp":"2024-01-15T10:30:00Z","name":"Meeting"}
}

2. 数字类型转为字符串

type Product struct {
    ID     int64   `json:"id,string"`    // 序列化为字符串
    Price  float64 `json:"price,string"` // 序列化为字符串
    Name   string  `json:"name"`
}

func main() {
    p := Product{
        ID:    1001,
        Price: 29.99,
        Name:  "Laptop",
    }
    
    data, _ := json.Marshal(p)
    fmt.Println(string(data))
    // 输出: {"id":"1001","price":"29.99","name":"Laptop"}
    
    // 反序列化时也能正确解析
    var p2 Product
    json.Unmarshal(data, &p2)
    fmt.Printf("ID: %d, Price: %.2f\n", p2.ID, p2.Price)
}

3. 大整数处理(避免JavaScript精度丢失)

type Transaction struct {
    Amount   int64  `json:"amount,string"` // 大整数转为字符串
    Currency string `json:"currency"`
}

func main() {
    t := Transaction{
        Amount:   9223372036854775807, // int64最大值
        Currency: "USD",
    }
    
    data, _ := json.Marshal(t)
    fmt.Println(string(data))
    // 输出: {"amount":"9223372036854775807","currency":"USD"}
}

4. 自定义类型实现字符串标签

type CustomInt int

func (ci *CustomInt) UnmarshalJSON(data []byte) error {
    var s string
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    
    val, err := strconv.Atoi(s)
    if err != nil {
        return err
    }
    
    *ci = CustomInt(val)
    return nil
}

func (ci CustomInt) MarshalJSON() ([]byte, error) {
    return json.Marshal(strconv.Itoa(int(ci)))
}

type Data struct {
    Value CustomInt `json:"value"` // 自动使用字符串格式
}

func main() {
    jsonStr := `{"value":"123"}`
    var d Data
    json.Unmarshal([]byte(jsonStr), &d)
    fmt.Printf("Value: %d\n", d.Value)
}

常见问题解决

如果遇到解析失败,检查以下几点:

  1. JSON格式必须匹配
// 正确:JSON中的数字是字符串格式
jsonStr := `{"id":"1001","name":"test"}`

// 错误:JSON中的数字是数值格式
jsonStr := `{"id":1001,"name":"test"}` // 解析会失败
  1. 使用json.RawMessage处理混合类型
type Flexible struct {
    Data json.RawMessage `json:"data"`
}

func main() {
    jsonStr := `{"data":"string_value"}`
    var f Flexible
    json.Unmarshal([]byte(jsonStr), &f)
    
    // 尝试作为字符串解析
    var strVal string
    if err := json.Unmarshal(f.Data, &strVal); err == nil {
        fmt.Println("String value:", strVal)
    }
}

字符串标签在需要精确控制JSON格式、避免数值精度丢失或与前端JavaScript交互时特别有用。确保序列化和反序列化时使用一致的格式即可避免解析失败。

回到顶部