自定义MarshalJSON()从不在Go中调用 [英] Custom MarshalJSON() never gets called in Go

查看:23
本文介绍了自定义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 Playround:http://play.golang.org/p/SJ05S8rAYN

尝试

推荐答案

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

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

问题是此变量不实现json.Marshaler接口,因为MarshalJSON不在myStructmethod set中(仅针对*myStruct)。

解决方法是(A)使MarshalJSON方法接受非指针接收器(这意味着它将获得结构的副本:如果结构很大,则可能代价高昂),或者(B)封送指向结构的指针(正如Kavu在评论中提到的那样)。

这种行为的原因是,Go不允许您获取指向存储在接口变量中的值的指针,而是要求您在想要访问它的时候复制该值。虽然该语言有将ms.MarshalJSON()转换为(&ms).MarshalJSON()作为使用指针接收器访问方法的一种方式的语法优势,但对于存储在接口变量中的值来说,这是做不到的。因此,该方法不被视为在其方法集中。

这篇关于自定义MarshalJSON()从不在Go中调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆