json: 无法将数字解组为类型为 string 的 Go 结构字段 .Amount

huangapple go评论93阅读模式
英文:

json: cannot unmarshal number into Go struct field .Amount of type string

问题

尝试使用tronscan.org获取Tron钱包的余额。

有时候Amount返回的是字符串,有时候返回的是类似这样的值:

"amount": 1.4900288469458728E-8

当返回这种类型的值时,我会得到这个错误:json: cannot unmarshal number into Go struct field .Amount of type string

这是我的结构体:

type trxResponse struct {
  Data []struct {
    Amount float64 `json:"amount,string"`
  } `json:"data"`
}

我该如何处理它?我正在使用https://github.com/goccy/go-json来解析JSON。

英文:

Trying to get balance of Tron wallet using tronscan.org

Sometimes Amount returns string, sometimes value like this

"amount": 1.4900288469458728E-8

When it returns value of this type i get this error json: cannot unmarshal number into Go struct field .Amount of type string

Here is my struct:

type trxResponse struct {
  Data []struct {
    Amount float64 `json:"amount,string"`
  } `json:"data"`
}

How can I handle it? To unmarshal json i'm using https://github.com/goccy/go-json

答案1

得分: 1

由于amount字段具有不同的类型,可以将其声明为interface{}类型,这将解决解组错误。

type trxResponse struct {
  Data []struct {
    Amount interface{} `json:"amount"`
  } `json:"data"`
}

然后可以根据需要将其转换为float64string类型。

英文:

As the amount field has different types, it can be declared as interface{} type, this will solve unmarshaling error.

type trxResponse struct {
  Data []struct {
    Amount interface{} `json:"amount"`
  } `json:"data"`
}

This can then be typecast from/to float64 or string as needed..

答案2

得分: 1

你可以通过声明自定义的UnmarshalJSON方法来实现Unmarshaler接口,该方法将根据类型处理amount字段。

type trxData struct {
	Amount float64 `json:"amount"`
}

type trxResponse struct {
	Data []trxData `json:"data"`
}

// UnmarshalJSON 处理不同类型的 amount 字段的自定义方法
func (d *trxData) UnmarshalJSON(data []byte) error {
	var objMap map[string]*json.RawMessage

	// 将 JSON 反序列化为原始消息
	err := json.Unmarshal(data, &objMap)
	if err != nil {
		return err
	}

	var amount float64 // 尝试反序列化为 float64
	if rawMsg, ok := objMap["amount"]; ok {
		if err := json.Unmarshal(*rawMsg, &amount); err != nil {
			// 如果失败,反序列化为字符串
			var amountStr string
			if err := json.Unmarshal(*rawMsg, &amountStr); err != nil {
				return err
			}
			amount, err = strconv.ParseFloat(amountStr, 64)
			if err != nil {
				return err
			}
		}
	}

	d.Amount = amount

	return nil
}

以上是处理amount字段的自定义UnmarshalJSON方法的示例代码。

英文:

You can implement the Unmarshaler interface by declaring custom UnmarshalJSON method, which will handle the amount field according to the type.


type trxData struct {
	Amount float64 `json:"amount"`
}

type trxResponse struct {
	Data []trxData `json:"data"`
}

// UnmarshalJSON custom method for handling different types
// of the amount field.
func (d *trxData) UnmarshalJSON(data []byte) error {
	var objMap map[string]*json.RawMessage

	// unmarshal json to raw messages
	err := json.Unmarshal(data, &objMap)
	if err != nil {
		return err
	}

	var amount float64 // try to unmarshal to float64
	if rawMsg, ok := objMap["amount"]; ok {
		if err := json.Unmarshal(*rawMsg, &amount); err != nil {
			// if failed, unmarshal to string
			var amountStr string
			if err := json.Unmarshal(*rawMsg, &amountStr); err != nil {
				return err
			}
			amount, err = strconv.ParseFloat(amountStr, 64)
			if err != nil {
				return err
			}
		}
	}

	d.Amount = amount

	return nil
}

huangapple
  • 本文由 发表于 2022年8月23日 06:15:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/73451511.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定