英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论