英文:
Not able to marshal json.RawMessage while []byte works fine
问题
以下是翻译好的内容:
一个可复现的示例可以在这里找到:https://go.dev/play/p/wNyhezDfxVt
我想要使用json.Marshal(...)
来编组一个包含json.RawMessage
字段的结构体。
type Container1 struct {
OldValue json.RawMessage `json:"old"`
NewValue json.RawMessage `json:"new"`
}
然而,它报告了以下错误:
error calling MarshalJSON for type json.RawMessage: invalid character 'h' looking for beginning of value
将json.RawMessage
更改为[]byte
可以解决此问题,但请注意,json.RawMessage
实际上就是[]byte
:
// RawMessage是一个原始编码的JSON值。
// 它实现了Marshaler和Unmarshaler接口,可以用于延迟JSON解码或预先计算JSON编码。
type RawMessage []byte
我仍然希望能够使用json.RawMessage
,有什么帮助吗?谢谢!
英文:
A reproducible example can be found here https://go.dev/play/p/wNyhezDfxVt
I want to marshal (json.Marshal(...)
) a struct with json.RawMessage
fields.
type Container1 struct {
OldValue json.RawMessage `json:"old"`
NewValue json.RawMessage `json:"new"`
}
However, it complains about the below error:
error calling MarshalJSON for type json.RawMessage: invalid character 'h' looking for beginning of value
Changing json.RawMessage
to []byte
fix the issue, but note that json.RawMessage
is nothing but []byte
:
// RawMessage is a raw encoded JSON value.
// It implements Marshaler and Unmarshaler and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawMessage []byte
I want to be still able to use json.RawMessage
, any help? Thanks!
答案1
得分: 3
json.RawMessage
类型被期望保存有效的JSON,因为它将按原样(raw)序列化。
当你使用[]byte("hello")
初始化一个json.RawMessage
字段时,你将字符串字面量"hello"转换为[]byte
类型,其内容为hello
(没有引号)。然后json.Marshal
失败,因为你需要引号"
使其成为有效的JSON字符串。要保留引号,你需要使用用反引号括起来的未转义的字符串字面量。
将你的结构体初始化更改为以下内容即可正常工作:
c1 := Container1{
[]byte(`"hello"`),
[]byte(`"world"`),
}
而Container2
中的[]byte
切片不会引起错误,尽管它们保存了相同的字节内容,这是因为json.Marshal
默认将字节切片序列化为base64编码。
事实上,在修复你的代码后,两个输出的JSON看起来是不同的:
使用json.RawMessage
:
{"old":"hello","new":"world"}
使用[]byte
:
{"old":"aGVsbG8=","new":"d29ybGQ="}
英文:
The type json.RawMessage
is expected to hold valid JSON, because it will be serialized as-is (raw).
When you initialize a json.RawMessage
field with []byte("hello")
, you're converting to []byte
, the string literal "hello"
, whose content is hello
without quotes. Then json.Marshal
fails, because you need the quotes "
for it to be a valid JSON string. To keep the quotes, you have to use an unescaped string literal enclosed in backticks.
Changing the initialization of your struct to this will work:
c1 := Container1{
[]byte(`"hello"`),
[]byte(`"world"`),
}
The []byte
slice in Container2
instead doesn’t cause errors despite holding the same byte content simply because json.Marshal
defaults to serializing byte slices as base64.
As a matter of fact, after fixing your playground, the two output JSON look different:
From json.RawMessage
:
{"old":"hello","new":"world"}
From []byte
:
{"old":"aGVsbG8=","new":"d29ybGQ="}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论