json - 自定义 MarshalJSON() 永远不会在 Go 中被调用

我编写了 MarshalJSONUnmarshalJSON 的自定义版本。我的 UnmarshalJSON 以我想要的方式被调用,但我无法让它与 MarshalJSON 一起工作。这是总结我的问题的代码:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
    "os"
)

type myStruct struct {
    Data string `json:"data"`
}

func (s *myStruct) MarshalJSON() ([]byte, error) {
    return []byte(`{"data":"charlie"}`), nil
}

func (s *myStruct) UnmarshalJSON(b []byte) error {
    // Insert the string directly into the Data member
    return json.Unmarshal(b, &s.Data)
}

func main() {
    // Create a struct with initial content "alpha"
    ms := myStruct{"alpha"}

    // Replace content with "bravo" using custom UnmarshalJSON() (SUCCESSFUL)
    if err := json.NewDecoder(bytes.NewBufferString(`"bravo"`)).Decode(&ms); err != nil {
        log.Fatal(err)
    }

    // Use custom MarshalJSON() to get "charlie" back (UNSUCCESSFUL)
    if err := json.NewEncoder(os.Stdout).Encode(ms); err != nil {
        log.Fatal(err)
    }

    // Trying another method (UNSUCCESSFUL)
    if ret, err := json.Marshal(ms); err != nil {
        log.Fatal(err)
    } else {
        fmt.Println(string(ret))
    }

    // Verify that the Marshaler interface is correctly implemented
    var marsh json.Marshaler
    marsh = &ms
    ret, _ := marsh.MarshalJSON()
    fmt.Println(string(ret)) // Prints "charlie"
}

简而言之,程序以两种方式“自动”编码struct,最后手动调用MarshalJSON。我想要的响应是 "charlie"。运行代码会生成以下输出:

{"data":"bravo"}
{"data":"bravo"}
{"data":"charlie"}

去 Go Playground 试试吧:http://play.golang.org/p/SJ05S8rAYN

最佳答案

在这部分代码中,ms 被复制到 interface{} 变量中:

// Trying another method (UNSUCCESSFUL)
if ret, err := json.Marshal(ms); err != nil {

问题是这个变量没有实现 json.Marshaler 接口(interface),因为 MarshalJSON 不在 method set 中。对于 myStruct(仅适用于 *myStruct)。

解决方法是 (a) 让您的 MarshalJSON 方法采用非指针接收器(这意味着它会获取结构的副本:如果它很大,可能会很昂贵),或者( b) 编码指向结构的指针(正如 Kavu 在评论中提到的那样)。

这种行为的原因是 Go 不允许您将指针指向存储在接口(interface)变量中的值,而是要求您在想要访问该值时复制该值。虽然该语言具有将 ms.MarshalJSON() 转换为 (&ms).MarshalJSON() 作为使用指针接收器访问方法的语法糖,但这不能为存储在接口(interface)变量中的值完成。因此,该方法不被视为在其方法集中。

https://stackoverflow.com/questions/21390979/

相关文章:

json - 如何重用 Jersey 的 JSON/JAXB 进行序列化?

javascript - 在 HTML 数据属性上添加 JSON 是不是很糟糕?

java - 单元测试 Jersey Restful Services

java - Gson - 自动引号(“)转义?

javascript - 在 JavaScript 中将 JSON 对象转换为 CSV 格式

c# - 如何使用 Newtonsoft.Json 包在 C#(4.0) 中解析我的 json 字符

javascript - 在javascript中将json对象写入文本文件

java - 仅当不为空或不为空时 Gson 序列化字段

jquery - 通过 jQuery 将 JSON 数据发布到 ASP .NET MVC 4 Con

php - 通过 JSON 发送 HTML 代码