簡體   English   中英

在 Go 中將平面 JSON 解組為嵌套結構

[英]Unmarshall flat JSON into a nested struct in Go

我想從包含另一個結構的平面 JSON 創建一個嵌套結構:

type Todo struct {
    Todo_id   int    `json:"todo_id" db:"todo_id"`
    Todo_name string `json:"todo_name" db:"todo_name"`

    User_id int         `json:"user_id" db:"user_id"`
    Subs    []Sub       `json:"subs" db:"subs"`
    Times   Parsed_Time `json:"times" db:"times"`
}

當我解組 JSON 時,我收到“缺少目標名稱截止日期”錯誤,因為截止日期位於 Parsed_Time 結構內。 有沒有辦法自定義解組 JSON,以便在沒有錯誤的情況下省略部分 JSON? 我想單獨創建一個帶有空 Times 的 Todo 結構,然后再次運行 Unmarshal 以將截止日期和其余時間戳分別提取到另一個結構中。 這是為了避免向數據庫發出兩個單獨的 Get 請求。

是的 - 你可能已經知道如果一個類型實現了json.Unmarshaler ,它將在json.Unmarshal()被調用時使用該類型作為第二個參數。 經常發生的問題是需要將接收器的類型解組為自定義解組代碼的一部分。 這可以通過多種方式克服,其中最常見的是使用本地類型進行解組。 不過,您可以通過明智地使用類型別名來節省大量重復代碼。

我已經更新了您上面的代碼,以存根Todo的字段表示的類型,如下所示:

type Sub int

type ParsedTime struct {
    Deadline time.Time
    Created  time.Time
}

type Todo struct {
    ID   int          `json:"todo_id" db:"todo_id"`
    Name string       `json:"todo_name" db:"todo_name"`
    UserID int        `json:"user_id" db:"user_id"`
    Subs   []Sub      `json:"subs" db:"subs"`
    Times  ParsedTime `json:"-" db:"times"`
}

請注意,相關性的唯一變化是在調用 `json.Unmarshal 時忽略Times字段。 我只更改了字段名稱以讓我的 IDE 的 linter 閉嘴! 使用這些類型,我們可以定義一個自定義解組器,如下所示:

func (t *Todo) UnmarshalJSON(data []byte) error {
    type TodoJSON Todo

    todo := struct {
        *TodoJSON
        Deadline string `json:"deadline"`
    }{
        TodoJSON: (*TodoJSON)(t),
    }

    if err := json.Unmarshal(data, &todo); err != nil {
        return err
    }

    deadline, err := time.Parse(time.RFC3339, todo.Deadline)
    if err != nil {
        return err
    }

    t.Times.Deadline = deadline

    return nil
}

此代碼中使用了兩種關鍵技術。 首先,使用類型別名消除了直接使用Todo時會發生的無限遞歸。 其次,創建嵌入*Todo的本地類型消除了完全重新鍵入Todo類型字段的需要 - 只需要添加所需的Deadline字段。 我還假設Deadlinetime.Time以表明此代碼還允許在分配字段之前對其進行處理( time.Parse() )。

暫無
暫無

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

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