json - 如何为 Go 中从标量派生的类型实现 UnmarshalJSON?

标签 json go

我有一个简单的类型,可以在 Go 中实现子类型整数常量到字符串的转换,反之亦然。我希望能够自动将 JSON 中的字符串解码为这种类型的值。我不能,因为 UnmarshalJSON 没有给我返回或修改标量值的方法。它需要一个结构,其成员由 UnmarshalJSON 设置。 “,string”方法不适用于内置标量类型以外的其他类型。有没有办法为派生标量类型正确实现 UnmarshalJSON?

这是我所追求的一个例子。我希望它打印“Hello Ralph”四次,但它打印“Hello Bob”四次,因为 PersonID 没有更改。

package main

import (
    "encoding/json"
    "fmt"
)

type PersonID int

const (
    Bob PersonID = iota
    Jane
    Ralph
    Nobody = -1
)

var nameMap = map[string]PersonID{
    "Bob":    Bob,
    "Jane":   Jane,
    "Ralph":  Ralph,
    "Nobody": Nobody,
}

var idMap = map[PersonID]string{
    Bob:    "Bob",
    Jane:   "Jane",
    Ralph:  "Ralph",
    Nobody: "Nobody",
}

func (intValue PersonID) Name() string {
    return idMap[intValue]
}

func Lookup(name string) PersonID {
    return nameMap[name]
}

func (intValue PersonID) UnmarshalJSON(data []byte) error {
    // The following line is not correct
    intValue = Lookup(string(data))
    return nil
}

type MyType struct {
    Person   PersonID `json: "person"`
    Count    int      `json: "count"`
    Greeting string   `json: "greeting"`
}

func main() {
    var m MyType
    if err := json.Unmarshal([]byte(`{"person": "Ralph", "count": 4, "greeting": "Hello"}`), &m); err != nil {
        fmt.Println(err)
    } else {
        for i := 0; i < m.Count; i++ {
            fmt.Println(m.Greeting, m.Person.Name())
        }
    }
}

最佳答案

对 unmarshal 方法使用指针接收器。如果使用值接收器,则当方法返回时,对接收器的更改将会丢失。

unmarshal 方法的参数是 JSON 文本。解码 JSON 文本以获取删除所有 JSON 引用的纯字符串。

func (intValue *PersonID) UnmarshalJSON(data []byte) error {
  var s string
  if err := json.Unmarshal(data, &s); err != nil {
    return err
  }
  *intValue = Lookup(s)
  return nil
}

JSON 标记与示例 JSON 之间不匹配。我更改了 JSON 以匹配标记,但您可以以其他方式更改它。

if err := json.Unmarshal([]byte(`{"person": "Ralph", "count": 4, "greeting": "Hello"}`), &m); err != nil {

playground example

关于json - 如何为 Go 中从标量派生的类型实现 UnmarshalJSON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34618940/

相关文章:

go - 为什么指针在这个 Go 程序中失去了它的值(value)

go - 没有处理程序的 Mux 中间件

windows - 在 Windows 中调试 Go (golang) 代码

go - 如何在 html/template 中使用范围内的索引来遍历并行数组?

json - 使用 serde_json 序列化带有非字符串键的映射

ruby - 为什么这个 JSON 文件填充了上次哈希数据的 1747 倍?

javascript - 无法将 php 中的 json 编码值解析为 javascript/jquery 中的 JSON 解析

javascript - DotNetBrowser : passing a json string from .Net 到接受 json 对象的 JavaScript 函数

go - 在 gorilla mux 路由器上设置 404 NotFound 处理程序

javascript - array.push 不适用于嵌套 JSON 对象