英文:
Unmarshalling values in scientific notion to integers in Go
问题
在我的Go代码中,我正在处理从一个端点接收到的JSON数据。这个端点将大的数值使用科学计数法进行编码:
type Test struct {
Key string
Value int32
}
func main() {
data := []byte("{\"Key\": \"derp\", \"Value\": 3.898733e+06}")
var t *Test
err := json.Unmarshal(data, &t)
fmt.Printf("Error: %v\n", err)
fmt.Printf("Data: %v\n", t)
}
这里编码的值等同于标准表示法中的3,898,733。然而,这段代码打印出了一个错误:
json: cannot unmarshal number 3.898733e+06 into Go struct field Test.Value of type int32
这是有道理的,因为strconv
也无法将这个值从字符串解析出来。然而,我可以使用var i int32 = 3.898733e+06
,它可以编译并产生正确的结果。
那么,我该如何解决这个错误呢?
英文:
In my Go code, I was working to unmarshal a JSON payload we receive from an endpoint. This endpoint encodes large values in scientific notation:
type Test struct {
Key string
Value int32
}
func main() {
data := []byte("{\"Key\": \"derp\", \"Value\": 3.898733e+06}")
var t *Test
err := json.Unmarshal(data, &t)
fmt.Printf("Error: %v\n", err)
fmt.Printf("Data: %v\n", t)
}
The encoded value here is equivalent to 3,898,733 in standard notation. However, this code prints an error:
> json: cannot unmarshal number 3.898733e+06 into Go struct field Test.Value of type int32
This makes sense because strconv
also fails to parse this value from a string. However, I can do var i int32 = 3.898733e+06
and that compiles and produces the correct answer.
So, how can I address this error?
答案1
得分: 1
声明var i int32 = 3.898733e+06
是有效的,因为该表达式中的字面量是一个无类型常量,无类型常量根据上下文进行求值。在这种情况下,即使它被写成浮点数,它在编译时被解释为int32。这不会在运行时发生。
有几种选项可以使其适用于JSON编组:
1)将Value
声明为json.Number
。这样,您可以尝试将其解析为int64,如果失败,则解析为float64,并转换为int64,希望不会丢失精度。
2)定义一个自定义类型并自行进行解组:
type LongInt int32
func (i *LongInt) UnmarshalJSON(data []byte) error {
// 自行解析数据并设置int值
// 可以使用big.Int吗?
}
3)将Value
声明为float64
。
英文:
The declaration var i int32 = 3.898733e+06
works because the literal in this expression is an untyped constant, and untyped constants are evaluated based on context. In this case, even though it is written as a floating-point number, it is interpreted as an int32 at compile time. This does not happen at runtime.
There are several options to make this work for JSON marshaling:
- Declare the
Value
asjson.Number
. This way you can try parsing it as int64, and if that fails, parse it as float64, and convert to int64 and hope you don't lose precision. - Define a custom type and unmarshal yourself:
type LongInt int32
func (i *LongInt) UnmarshalJSON(data []byte) error {
// Parse data yourself and set the int value
// Maybe use big.Int?
}
- Declare
Value
asfloat64
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论