英文:
Does Go correctly marshal float64 to JSON?
问题
使用go1.1.2 Win64,我有一个Go程序,它“marshal”一个包含float64的结构体。当float64的值不是整数时,例如1234.44,它会被“marshal”为浮点数(json.Marshal)。然而,当它是一个整数时,例如"1234.00",它会被编组为整数"1234"。当我在另一端(Dart)接收到它时,Dart(30188)将整数视为整数(在map - JSON.decode中)。因此,当浮点(double)数据的表示不包含小数点,并且我尝试从map中“提取”它作为double时,Dart程序会中止。
这个问题显然可以通过多种不同的方式解决(例如,将其转换为整数,然后再转换回浮点数),但我想知道是否有另一种(更好的)处理这种情况的方法。
有没有比将float64转换为整数更好的处理方法?
英文:
Using go1.1.2 Win64, I have a Go program that "marshal"'s a struct containing a float64. When the value of the float64 is not a whole number eg. 1234.44, then it gets "marshal"ed as a float (json.Marshal). When however it is a whole number eg. "1234.00" it is marshalled as an integer"1234". When I receive that at the other end (Dart), Dart (30188) treats the whole number as an integer (in map - JSON.decode). Consequently the Dart program aborts when the representation of the float (double) data doesn't contain a decimal point, and I attempt to "extract" it from the map as a double.
This can obviously be solved a number of different ways (eg. convert to integer and then convert back to float), however I wondered if there is another (better) way to handle this situation.
Is there another better way to handle this than to convert float64 to integer?
答案1
得分: 8
JSON,就像JavaScript一样,不区分整数和数字。
如果Dart将1234.00
与1234
区别对待,那么它对值的假设是不被JSON规范支持的。
虽然Go确实正确地编组了float64,但解决Dart假设问题的一种方法是在自己的类型上实现Marshaler接口:
type Number float64
func (n Number) MarshalJSON() ([]byte, error) {
// 也许有更好的方法。这只是一个示例
return []byte(fmt.Sprintf("%f", n)), nil
}
然后,您可以在将要编组的结构中使用自己的Number
类型,而不是float64
。这样,您可以确保您的数字始终带有小数点。
在Playground上的工作示例。
英文:
JSON, just like Javascript, doesn't differ between integers and numbers.
If Dart treats 1234.00
differently from 1234
, then it is making assumptions about the value not supported by the JSON specification.
While Go does indeed marshal float64 correctly, one way of getting around the problem with Dart's assumption is by implementing the Marshaler interface on your own type:
type Number float64
func (n Number) MarshalJSON() ([]byte, error) {
// There are probably better ways to do it. It is just an example
return []byte(fmt.Sprintf("%f", n)), nil
}
And then you can use your own Number
type, instead of float64
, in the structs that you will Marshal. This way you can make sure that your numbers will always be marshaled with a decimal point.
Working example on Playground
答案2
得分: 3
以下是翻译好的内容:
以下似乎是解决方案(对我而言)。整数方法 toDouble() 也适用于 "num"(反之亦然)。在使用 Dart 处理可以被解释为 double 或 int 的 JSON 和货币值时,需要使用 "as num",然后使用内置的 toDouble() 方法。
示例(Go):
type cuAcctRow struct {
.....
D_AcctBal float64
.....
}
if baJsAcctDet, oOsError = json.Marshal(uAcctRow); oOsError != nil {
示例(Dart):
Map mAcctData = json.parse(sResponse);
double dAcctBal = (mAcctData['D_AcctBal'] as num).toDouble();
我不知道为什么 Dart 不允许直接将整数赋值给 double,但我相信肯定有一个很好的理由。
英文:
The following appears to be (to me) the solution. The integer method toDouble() also works with "num" (or vice versa). It appears to me that when working with json and monetary values that could be interpreted as either double or int by Dart, that it is necessary to use "as num" and then use the built-in method toDouble().
Example (Go):
type cuAcctRow struct {
.....
D_AcctBal float64
.....
}
if baJsAcctDet, oOsError = json.Marshal(uAcctRow); oOsError != nil {
Example (Dart):
Map mAcctData = json.parse(sResponse);
double dAcctBal = (mAcctData['D_AcctBal'] as num).toDouble();
I don't know why Dart doesn't allow direct assignment of integer to double, but I'm sure there is a good reason.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论