如何在编组JSON时将字段内联?

3

我有一个名为MonthYear的类型定义如下:

type MonthYear time.Time

func (my *MonthYear) MarshalJSON() ([]byte, error) {
    t := time.Time(*my)

    return json.Marshal(&struct {
        Month int `json:"month"`
        Year  int `json:"year"`
    }{
        Month: int(t.Month()) - 1,
        Year:  t.Year(),
    })
}

我包含了很多不同的结构体,比如:
type Event struct {
    Name string `json:"name"`
    Date MonthYear
}

type Item struct {
    Category string `json:"category"`
    Date     MonthYear
}

我该如何将MonthYear类型内联,以便生成的JSON没有任何嵌入对象?
我希望结果看起来像{ "name": "party", "month": 2, "year": 2017 }{ "category": "art", "month": 3, "year": 2016 },而无需为每个结构编写MarshalJSON。

如果Brad Fitzpatrick的回答还不足够满足你,那我不知道还有什么能满足你了。https://github.com/golang/go/issues/6213 - undefined
如果你非常想要的话,你可以使用go generate来编写Marshall JSON函数。 - undefined
1个回答

6

我知道这不是你想得到的答案,但在 encoding/json 包添加内联支持之前,你可以使用以下解决方法:

将你的 MonthYear 改为一个结构体,例如:

type MonthYear struct {
    t     time.Time
    Month int `json:"month"`
    Year  int `json:"year"`
}

一个可选的、用于方便创建的构造函数:

func NewMonthYear(t time.Time) MonthYear {
    return MonthYear{
        t:     t,
        Month: int(t.Month()) - 1,
        Year:  t.Year(),
    }
}

使用嵌入(匿名字段)而不是常规(命名)字段,以在JSON表示中获得“扁平化”/内联的效果:

type Event struct {
    Name string `json:"name"`
    MonthYear
}

type Item struct {
    Category string `json:"category"`
    MonthYear
}

作为额外的一点,您可以直接引用字段,比如 Event.Year 或者 Event.Month,这很方便。
测试一下:
evt := Event{Name: "party", MonthYear: NewMonthYear(time.Now())}
fmt.Println(json.NewEncoder(os.Stdout).Encode(evt), evt.Year)

itm := Item{Category: "Tool", MonthYear: NewMonthYear(time.Now())}
fmt.Println(json.NewEncoder(os.Stdout).Encode(itm))

输出结果(在Go Playground上进行测试):

{"name":"party","month":10,"year":2009}
<nil> 2009
{"category":"Tool","month":10,"year":2009}
<nil>

注意:这里不涉及MonthYear.t时间字段(也不进行编组)。如果原始的time.Time不需要,您可以将其删除。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接