当将int64字节转换为JSON时,会出现Go JSON Marshaller错误。

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

Go JSON Marshaller errors when converting int64 bytes

问题

我正在编写一个时间别名,将一些时间转换为Unix格式的JSON Marshal(在其中留下了一些我实验性的测试代码)。

type NotifyTime time.Time

// MarshalJSON 实现了 marshaller 接口。将 time.Time 转换为字节中的 Unix 时间
func (t NotifyTime) MarshalJSON() ([]byte, error) {
    // unixTime := time.Time(t).Unix()
    unixTime := 1626132059 // unixTime := time.Now().Unix()
    buffer := make([]byte, 8)
    binary.PutVarint(buffer, int64(unixTime))
    // binary.LittleEndian.PutUint64(buffer, uint64(unixTime))

    // 尝试转换回来
    fmt.Println(string(buffer))
    unixIntValue := int64(binary.LittleEndian.Uint64(buffer))
    fmt.Println(unixIntValue)

    return buffer, nil
}

当我对一个包含 NotifyTime 结构的对象运行 json.Marshal 时,它报错,错误信息如下:

json: error calling MarshalJSON for type notify.NotifyTime: invalid character '¶' looking for beginning of value

以下是相关的代码片段:

type TestMe struct {
    Time NotifyTime `json:"time"`
}
testJSON := TestMe{
    Time: NotifyTime(time.Now()),
}
marshalled, err := json.Marshal(testJSON)

我已经改为将其转换为字符串进行编组,但仍然对此情况感到好奇。当我逐步执行代码时,似乎是因为在 go/1.16.2/libexec/src/encoding/json/indent.go 的 compact 函数中,它在循环遍历 JSON 的编组字节时,第一个(第0个)字节未通过 go/1.16.2/libexec/src/encoding/json/scanner.go 的检查。

英文:

I am writing a time alias to JSON Marshal some time into a Unix format (left some of my experimenting test code in there

type NotifyTime time.Time

// MarshalJSON implements marshaller interface. Marshals time.Time into unix time in bytes
func (t NotifyTime) MarshalJSON() ([]byte, error) {
	// unixTime := time.Time(t).Unix()
	unixTime := 1626132059 // unixTime := time.Now().Unix()
	buffer := make([]byte, 8)
	binary.PutVarint(buffer, int64(unixTime))
	// binary.LittleEndian.PutUint64(buffer, uint64(unixTime))

	// try to convert back
	fmt.Println(string(buffer))
	unixIntValue := int64(binary.LittleEndian.Uint64(buffer))
	fmt.Println(unixIntValue)

	return buffer, nil
}

When I run json.Marshal on an object with NotifyTime struct, it errs, with the following,
json: error calling MarshalJSON for type notify.NotifyTime: invalid character '¶' looking for beginning of value

		type TestMe struct {
			Time NotifyTime `json:"time"`
		}
		testJSON := TestMe{
			Time: NotifyTime(time.Now()),
		}
		marshalled, err := json.Marshal(testJSON)

I have switched to marshalling it as a string, but still curious as to why this happens. When stepping through the code it seems to be because
on function compact on go/1.16.2/libexec/src/encoding/json/indent.go:17
it is looping over the marshalled bytes of the JSON
and the first (0th) byte fails the checks in
go/1.16.2/libexec/src/encoding/json/scanner.go:247

答案1

得分: 2

让我们暂时不考虑编码time.Time的方面,而是专注于将int64转换为JSON的方式。

binary.PutVarint使用适用于低级别的网络或文件格式的编码。对于常量1626132059,它会将其写入缓冲区[182 185 230 142 12 0 0 0]。第一个字符是UTF-8中的182 PILCROW SIGN。这就是为什么你会得到一个错误,类似于:

json: error calling MarshalJSON for type main.NotifyTime: invalid character '¶' looking for beginning of value

这不是一个有效的JSON值的开头。你需要找到一个int64的编码,它是一个JSON值,比如一个十进制数1626132059或一个十六进制数字的字符串"60ecce5b"

一般来说,当将二进制字符串值放入JSON时,你需要小心,因为它们可能包含需要转义的特殊字符。

英文:

Let's put aside the aspect of encoding a time.Time and lets focus on how the int64 is being turned into JSON.

binary.PutVarint uses an encoding that is appropriate for low level wire or file formats. For the constant 1626132059, this writes into buffer [182 185 230 142 12 0 0 0]. The first character is 182 PILCROW SIGN in UTF-8. This is where '¶' comes from. You are getting an error like:

json: error calling MarshalJSON for type main.NotifyTime: invalid character '¶' looking for beginning of value

This is not the beginning of a valid JSON value. You will need to find an encoding of int64 that is a JSON value, such as a decimal number 1626132059 or a string of hexadecimal digits "60ecce5b".

In general you need to be careful putting binary string values into JSON as these can contain special characters that need to be escaped.

huangapple
  • 本文由 发表于 2021年7月13日 08:15:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/68355115.html
匿名

发表评论

匿名网友

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

确定