MarshalJSON是一个字符串声明类型。

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

MarshalJSON a String Declared Type

问题

我已经创建了一个新的声明类型,并添加了一个方法来将值转换为JSON。

type TextOutput string

func (t *TextOutput) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf(`{"data": "%s"}`, t)), nil
}

当我尝试将该类型的实例转换为JSON时,我得到了原始值的返回。我错过了什么吗?

var t TextOutput
t = `Test test`
output, err := json.Marshal(t)
if err != nil {
    fmt.Println(err)
} else {
    fmt.Println(string(output))
}
// 输出 Test test。预期结果是 {"data": "Test test"}

你错过了在TextOutput类型的MarshalJSON方法中使用HTML实体编码的步骤。在fmt.Sprintf中,你应该使用%s而不是"%s"来格式化字符串。这样,你的代码应该是这样的:

func (t *TextOutput) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf(`{"data": "%s"}`, t)), nil
}

这样就能得到预期的结果了。

英文:

I have created a new declared type and added a method to marshal the value into JSON

type TextOutput string

func (t *TextOutput) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf(`{"data": "%s"}`, t)), nil
}

When I try to marshal an instance of the type I get the raw value returned. What am I missing?

var t TextOutput
t = `Test test`
output, err := json.Marshal(t)
if err != nil {
	fmt.Println(err)
} else {
	fmt.Println(string(output))
}
// prints Test Test. Expected {"data": "Test test"}

答案1

得分: 2

你必须将MarshalJSON接口定义为非指针类型。

func (t TextOutput) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf(`{"data": "%s"}`, t)), nil
}

播放链接:https://play.golang.org/p/lLK6zsAkOi

输出:

{"data":"测试测试"}
英文:

You have to define the MarshalJSON interface as a non-pointer.

func (t TextOutput) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf(`{"data": "%s"}`, t)), nil
}

Play Link: https://play.golang.org/p/lLK6zsAkOi

Output:

{"data":"Test test"}

答案2

得分: 1

问题的根源在于Go语言中接口的隐式满足方式。在这个特定的情况下,json.Marshal方法在运行时使用类型断言来判断给定的值是否实现了json.Marshaler接口。《Effective Go》中提到了这个情况。

你可以通过使用指针接收器来满足*TextOutput类型的json.Marshaler接口,代码如下:

func (t *TextOutput) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf(`{"data":"%s"}`, *t)), nil
}

为了使其正常工作,将引用传递给json.Marshal函数:

var t TextOutput
t = `Test test`
output, err := json.Marshal(&t)

然而,使用值接收器实现它可以确保TextOutput*TextOutput类型都实现了json.Marshaler接口,代码如下:

func (t TextOutput) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf(`{"data": "%s"}`, t)), nil
}
英文:

The root of the problem stems from how interfaces in Go are implicitly satisfied.
In this particular case, the json.Marshal method uses type assertion at runtime to see if the given value implements json.Marshaler. Effective Go mentions this very case.

You could have satisfied the json.Marshaler for the *TextOutput type using a pointer-receiver like so:

func (t *TextOutput) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf(`{"data":"%s"}`, *t)), nil
}

And for this to work properly, pass the reference to the json.Marshal function:

var t TextOutput
t = `Test test`
output, err := json.Marshal(&t) 

However, implementing it using a value-receiver ensures that both TextOutput and *TextOutput types implement json.Marshaler

func (t TextOutput) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf(`{"data": "%s"}`, t)), nil
}

huangapple
  • 本文由 发表于 2017年8月4日 02:50:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/45492320.html
匿名

发表评论

匿名网友

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

确定