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

Golang中JSON反序列化string/int64转int64失败如何解决?

解决JSON字段同时存在字符串与数值类型的反序列化问题

首先修正你原代码中的JSON语法错误:原字符串里的"id":"1000,和"id":"1001,未闭合引号,正确的JSON应为:

[{"id":"1000","price":"30"},{"id":"1001","price":50}]

针对字段类型不统一的问题,推荐以下两种解决方案:

方案一:自定义结构体的UnmarshalJSON方法(推荐)

给Item类型实现自定义反序列化逻辑,兼容字符串和数值类型的字段:

import (
	"encoding/json"
	"fmt"
	"strconv"
)

type Item struct {
	Id    int64 `json:"id"`
	Price int64 `json:"price"`
}

// 自定义UnmarshalJSON方法,处理多类型字段
func (i *Item) UnmarshalJSON(data []byte) error {
	// 定义临时结构体,用interface{}接收字段,兼容字符串和数值
	type tempItem struct {
		Id    interface{} `json:"id"`
		Price interface{} `json:"price"`
	}

	var temp tempItem
	if err := json.Unmarshal(data, &temp); err != nil {
		return err
	}

	// 处理Id字段
	switch val := temp.Id.(type) {
	case string:
		num, err := strconv.ParseInt(val, 10, 64)
		if err != nil {
			return fmt.Errorf("id字段转换失败:%w", err)
		}
		i.Id = num
	case float64: // JSON数值默认解析为float64
		i.Id = int64(val)
	default:
		return fmt.Errorf("不支持的id类型:%T", val)
	}

	// 处理Price字段
	switch val := temp.Price.(type) {
	case string:
		num, err := strconv.ParseInt(val, 10, 64)
		if err != nil {
			return fmt.Errorf("price字段转换失败:%w", err)
		}
		i.Price = num
	case float64:
		i.Price = int64(val)
	default:
		return fmt.Errorf("不支持的price类型:%T", val)
	}

	return nil
}

func HandleJsonData() {
	jsonData := []byte(`[{"id":"1000","price":"30"},{"id":"1001","price":50}]`)

	var items []Item
	err := json.Unmarshal(jsonData, &items)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Printf("反序列化结果:%+v\n", items)
}

原理说明

通过临时结构体的interface{}字段接收任意类型的JSON值,再通过类型断言判断字段实际类型,将字符串或float64转换为int64后赋值给目标结构体字段,完成兼容反序列化。

方案二:使用json.Number类型中转

利用json.Number类型可以同时接收字符串和数值类型的特性,先完成反序列化,再手动转换为int64:

import (
	"encoding/json"
	"fmt"
)

type TempItem struct {
	Id    json.Number `json:"id"`
	Price json.Number `json:"price"`
}

type Item struct {
	Id    int64 `json:"id"`
	Price int64 `json:"price"`
}

func HandleJsonData() {
	jsonData := []byte(`[{"id":"1000","price":"30"},{"id":"1001","price":50}]`)

	var tempItems []TempItem
	err := json.Unmarshal(jsonData, &tempItems)
	if err != nil {
		fmt.Println(err)
		return
	}

	// 转换为业务结构体
	var items []Item
	for _, temp := range tempItems {
		id, err := temp.Id.Int64()
		if err != nil {
			fmt.Printf("转换id失败:%v\n", err)
			continue
		}
		price, err := temp.Price.Int64()
		if err != nil {
			fmt.Printf("转换price失败:%v\n", err)
			continue
		}
		items = append(items, Item{Id: id, Price: price})
	}

	fmt.Printf("反序列化结果:%+v\n", items)
}

原理说明

json.Number是标准库提供的类型,能自动解析JSON中的字符串或数值类型,之后调用其Int64()方法即可转换为目标类型,适合需要灵活处理字段的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:15:31