簡體   English   中英

我可以使用 MarshalJSON 向 golang 中的 json 編碼添加任意字段嗎?

[英]Can I use MarshalJSON to add arbitrary fields to a json encoding in golang?

假設我已經編寫了以下代碼片段。 此處的操場上的完整代碼適合那些有興趣的人。

type Book struct {
  Title        string
  Author       string
}

func main() {
  ms := Book{"Catch-22", "Joseph Heller"}
  out, err := json.MarshalIndent(ms, "", "  ")
  if err != nil {
    log.Fatalln(err)
  }
  fmt.Println(string(out))
}

此代碼輸出以下內容,完全符合我的預期:

{
  "Title": "Catch-22",
  "Author": "Joseph Heller"
}

假設有一段時間我想向 JSON 輸出添加一個字段,但不將其包含在Book結構中。 也許是一種類型:

{
  "Title": "Catch-22",
  "Author": "Joseph Heller",
  "Genre": "Satire"
}

我可以使用MarshalJSON()Marshal()上的 JSON 負載添加任意字段嗎? 就像是:

func (b *Book) MarshalJSON() ([]byte, error) {
    // some code
}

其他答案讓我認為這應該是可能的,但我正在努力弄清楚實現。

這是一個比我上一個更好的答案。

type FakeBook Book

func (b Book) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        FakeBook
        Genre string
    }{
        FakeBook: FakeBook(b),
        Genre:    "Satire",
    })
}

由於匿名結構字段是“合並的”(有一些額外的考慮),我們可以使用它來避免重新映射單個字段。 請注意使用FakeBook類型來避免否則會發生的無限遞歸。

游樂場: http : //play.golang.org/p/21YXhB6OyC

這個問題的一個可能答案是結構文字(此處的代碼),盡管我希望有一些更通用的東西,它不需要重新映射結構的所有字段:

func (b *Book) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct{
        Title    string
        Author   string
        Genre    string
    } {
        Title: b.Title,
        Author: b.Author,
        Genre: "Satire",
    })
}

編組map是解決問題的另一種方法。

tmap := make(map[string]interface{})

tmap["struct"] = struct {
    StructValue string `json:"struct_value"`
}{
    "Value 02",
}

tmap["string"] = "Value 01"

out, err := json.MarshalIndent(tmap, "", "  ")
if err != nil {
    log.Fatalln(err)
}
fmt.Println(string(out))

這將輸出:

{
  "string": "Value 01",
  "struct": {
    "struct_value": "Value 02"
  }
}

如果您有許多任意鍵名,這可能是一個很好的解決方案。

游樂場: https : //play.golang.org/p/Umy9rtx2Ms

這是處理它的一種方法:

type Object struct {
    A string
    B int
    Extra map[string]interface{} `json:"-"`
}

func (o Object) MarshalJSON() ([]byte, error) {
    type Object_ Object
    b, err := json.Marshal(Object_(o))
    if err != nil {
        return nil, err
    }
    if o.Extra == nil || len(o.Extra) == 0 {
        return b, nil
    }
    m, err := json.Marshal(o.Extra)
    if err != nil {
        return nil, err
    }
    if len(b) == 2 {
        return m, nil
    } else {
        b[len(b)-1] = ','
        return append(b, m[1:]...), nil
    }
}

您可以將任何其他字段添加到Extra地圖,它們將顯示在輸出中而不會嵌套。

去游樂場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM