Serialize deserialize from Go int64/uint64 from/to Javascript string

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

Serialize deserialize from Go int64/uint64 from/to Javascript string

问题

是否可以修改JSON序列化和反序列化,使得像这样的结构体:

type Foo struct {
   A int64
   B uint64
   // 还有其他使用int64和uint64的字段,有很多类似的结构体
}

x := Foo{A: 1234567890987654, B: 987654321012345678}
byt, err := json.Marshal(x)
fmt.Println(err)
fmt.Println(string(byt))

//                                 9223372036854775808      9223372036854775808
err = json.Unmarshal([]byte(`{"A":"12345678901234567", "B":"98765432101234567"}`), &x)
// ^ 必须加引号,因为JavaScript无法正确表示这些值(2^53)
// ^ json: 无法将字符串解组为类型为int64的Go结构体字段Foo.A
fmt.Println(err)
fmt.Printf("%#v\n", x)
// main.Foo{A:1234567890987654, B:0xdb4da5f44d20b4e}

进行修改,使其能够接收JSON字符串,但解析为int64/uint64,并且可以将int64/uint64反序列化为JSON字符串,而无需修改结构体或结构体标签。

英文:

Is it possible to modify json serialization and deserialization so that a struct like this:

type Foo struct {
   A int64
   B uint64
   // and other stuff with int64 and uint64 and there's a lot of struct that are like this
}

x := Foo{A: 1234567890987654, B: 987654321012345678}
byt, err := json.Marshal(x)
fmt.Println(err)
fmt.Println(string(byt))

//                                 9223372036854775808      9223372036854775808
err = json.Unmarshal([]byte(`{"A":"12345678901234567", "B":"98765432101234567"}`), &x)
// ^ must be quoted since javascript can't represent those values properly (2^53)
// ^ json: cannot unmarshal string into Go struct field Foo.A of type int64
fmt.Println(err)
fmt.Printf("%#v\n", x)
// main.Foo{A:1234567890987654, B:0xdb4da5f44d20b4e}

https://play.golang.org/p/dHN-FcJ7p-N

So that It could receive json string but parsed as int64/uint64, and can deserialize int64/uint64 as json string without have to modify the struct or struct tag at all

答案1

得分: 6

在JSON结构标签中使用string选项。它专门用于这种情况:

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

type Foo struct {
	A int64  `json:"A,string"`
	B uint64 `json:"B,string"`
}

func main() {
	x := &Foo{}
	_ = json.Unmarshal([]byte(`{"A":"12345678901234567", "B":"98765432101234567"}`), x)

	fmt.Println(x) // &{12345678901234567 98765432101234567}

	b, _ := json.Marshal(x)

	fmt.Println(string(b)) // {"A":"12345678901234567","B":"98765432101234567"}
}

Playground: https://play.golang.org/p/IfpcYOlcKMo

如果无法修改现有的结构标签(但您的示例中没有),那么您必须在自定义的UnmarshalJSONMarshalJSON方法中重新实现此string标签选项的功能。

英文:

Use the string option in the JSON struct tag. It's designed exactly for this use case:

> The "string" option signals that a field is stored as JSON inside a JSON-encoded string. It applies only to fields of string, floating point, integer, or boolean types. This extra level of encoding is sometimes used when communicating with JavaScript programs

type Foo struct {
	A int64  `json:"A,string"`
	B uint64 `json:"B,string"`
}

func main() {
	x := &Foo{}
	_ = json.Unmarshal([]byte(`{"A":"12345678901234567", "B":"98765432101234567"}`), x)

	fmt.Println(x) // &{12345678901234567 98765432101234567}

	b, _ := json.Marshal(x)

	fmt.Println(string(b)) // {"A":"12345678901234567","B":"98765432101234567"}
}

Playground: https://play.golang.org/p/IfpcYOlcKMo

If you can't modify existing struct tags (but your example has none), then you have to reinvent the implementation of this string tag option in a custom UnmarshalJSON and MarshalJSON methods.

huangapple
  • 本文由 发表于 2021年8月20日 02:03:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/68852672.html
匿名

发表评论

匿名网友

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

确定