使用自定义MarshalJSON更改结构中的JSON标签 [英] Changing JSON tags in struct with custom MarshalJSON

查看:70
本文介绍了使用自定义MarshalJSON更改结构中的JSON标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们得到一些JSON输入,将其解组,执行一些工作,然后将其编组并运送到其他地方.我们得到的JSON可能有一个名为"user"的字段.当我们编组回JSON时,我们需要将用户"字段更改为用户名".我们可以通过创建一个具有所有相同字段但具有不同JSON标记的新结构来完成此操作,但这似乎有点麻烦.我以为自定义编组器可以在这里工作,但我有点卡住了.考虑以下代码.

We get some JSON input, unmarshal, perform some work, then marshal and ship off somewhere else. The JSON we get may have a field named "user". When we marshal back to JSON we need to have that field "user" changed to "username". We can do this by creating a new struct with all the same fields, but different JSON tags, but that seemed a bit cumbersome. I thought a custom marshaller would work here, but I'm a bit stuck. Consider the following code.

package main

import (
    "encoding/json"
    "fmt"
)

type StructA struct {
    Username string `json:"user"`
    Process  string `json:"process"`
}

func main() {

    var test1 StructA
    err := json.Unmarshal([]byte(`{"user": "user123", "process": "something"}`), &test1)
    if err != nil {
        fmt.Println(err)
    }

    // do some work with test1

    jsonByte, err := json.Marshal(&test1)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(string(jsonByte))

}

func (u *StructA) MarshalJSON() ([]byte, error) {
    type Alias StructA
    return json.Marshal(&struct {
        Username string `json:"username"`
        *Alias
    }{
        Username: u.Username,
        Alias:    (*Alias)(u),
    })
}

https://play.golang.org/p/_w0rlQrcgrW

理想情况下,这将允许我将该字段上的JSON标签从用户"更改为用户名".但是,我同时获得了用户名"和用户".

Ideally this would allow me to change the JSON tag on that field from "user" to "username". However, I get both "username" and "user".

{"username":"user123","user":"user123","process":"something"}

我当然可以创建一个全新的结构,以所需的标签镜像StructA,但是我不必复制每个字段,也不必担心使这两个结构保持同步.这不是世界末日,但这似乎不是一个好方法.

I certainly could create an entirely new struct that mirrors StructA with the tags I want, but I don't have to have to copy every single field and worry about keeping those two structs in sync. It's not the end of the world, but it doesn't seem like a good approach.

很明显,我要寻找的最终结果如下:

To be clear, the end result I'm looking for is the following:

{"username":"user123","process":"something"}

我敢肯定,我在这里缺少一些琐碎的事情,但这已经是一个漫长的一周,我们将不胜感激.谢谢!

I'm sure I'm missing something trivial here, but it's been a long week and any assistance would be appreciated. Thanks!

推荐答案

一个选项可能是让一个结构具有不变的值,然后是2个替代结构,它们都包含该结构且仅具有变化的值.然后,您可以将其中一个用于编组,而将第二个用于编组.

One option could be to have one struct with the non-changing values and than 2 alternative structs which both include that struct and have only the changing values. You then use one for unmarshaling and the second one for marshaling.

type StructA struct {
    Process  string `json:"process"`
    ...
}

type WithUser struct {
    StructA
    Username `json:"user"`
}

type WithUsername struct {
    StructA
    Username `json:"username"`
}

这将需要多个结构,但每个结构都没有重复,并且可以很灵活地包含在其中,而不是将要更改的内容硬编码为自定义编组函数.

This would require multiple structs but no duplication in each one and can be quite flexible in what you include, instead of hard coding what you want to change into a custom marshal function.

这篇关于使用自定义MarshalJSON更改结构中的JSON标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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