我用其他语言(如 java)创建自己的类型作为枚举值。我实现了该类型的反序列化 UnmarshalJSON 方法,发现 marshal 无法转换为自定义类型
package main
import (
"encoding/json"
"fmt"
)
type Mode string
const (
UPDATE Mode = "update"
INSERT Mode = "insert"
)
func (receiver Mode) String() string {
switch receiver {
case UPDATE:
return string(UPDATE)
case INSERT:
return string(INSERT)
default:
return "UNRECOGNIZED"
}
}
func (receiver Mode) MarshalJSON() ([]byte, error) {
return []byte(`"` + receiver.String() + `"`), nil
}
func (receiver Mode) UnmarshalJSON(data []byte) error {
receiver = Mode(data[1 : len(data)-1])
return nil
}
func main() {
var source Mode = "update"
tmp, err := json.Marshal(source)
if err != nil {
panic(err)
}
var received Mode
err = json.Unmarshal(tmp, &received)
if err != nil {
panic(err)
}
fmt.Println("source: ", source, "; received: ", received)
}
Run Code Online (Sandbox Code Playgroud)
并查看输出:source: update ; received: UNRECOGNIZED。如何以正确的方式为这种类型编写 UnmarshalJSON?
Unmarshal()必须修改接收器,因此它必须是一个指针,请参阅此工作示例:
func (receiver *Mode) UnmarshalJSON(data []byte) error {
*receiver = Mode(data[1 : len(data)-1])
return nil
}
Run Code Online (Sandbox Code Playgroud)
这将输出(在Go Playground上尝试):
source: update ; received: update
Run Code Online (Sandbox Code Playgroud)
请参阅相关问题:How to json unmarshalling with custom attribute type in Go
另外,您不应该自己处理生成/解析string,不能保证输入是有效的 JSON string,也不应该处理正确的转义。把它留给包裹encoding/json。
因此,最好使用这个实现:
func (receiver Mode) MarshalJSON() ([]byte, error) {
return json.Marshal(receiver.String())
}
func (receiver *Mode) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*receiver = Mode(s)
return nil
}
Run Code Online (Sandbox Code Playgroud)
这将处理无效输入并始终生成有效的 JSON 输出。它的输出是相同的,请在Go Playground上尝试一下。