Общий подход для маршалинга времени структуры. Поля времени в JSON с пользовательским форматированием - PullRequest
0 голосов
/ 21 сентября 2018

Моя модель данных определяет несколько структур, которые имеют два общих поля: StartDate и EndDate.Мне нужно, чтобы эти два поля были отформатированы как 2018-09-21 в маршализованном JSON, поэтому структуры реализуют интерфейс Marshaller:

type Results struct {
    Source     string    `json:"source"`
    StartDate  time.Time 
    EndDate    time.Time 
}

type WeightedResults struct {
    Source          string           `json:"source"`
    StartDate       time.Time        
    EndDate         time.Time        
}

func (r Results) MarshalJSON() ([]byte, error) {
    type Alias Results
    if equalDate(r.StartDate, r.EndDate) {
        return json.Marshal(&struct {
            Date string `json:"date"`
            Alias
        }{
            Date:  r.StartDate.Format(dateFormat),
            Alias: (Alias)(r),
        })
    }    
    return json.Marshal(&struct {
        StartDate string `json:"start_date"`
        EndDate   string `json:"end_date"`
        Alias
    }{
        StartDate: r.StartDate.Format("2006-01-02"),
        EndDate:   r.EndDate.Format("2006-01-02"),
        Alias:     (Alias)(r),
    })
}

func (r WeightedResults) MarshalJSON() ([]byte, error) {
    type Alias WeightedResults
    if equalDate(r.StartDate, r.EndDate) {
        return json.Marshal(&struct {
            Date string `json:"date"`
            Alias
        }{
            Date:  r.StartDate.Format(dateFormat),
            Alias: (Alias)(r),
        })
    } 
    return json.Marshal(&struct {
        StartDate string `json:"start_date"`
        EndDate   string `json:"end_date"`
        Alias
    }{
        StartDate: r.StartDate.Format("2006-01-02"),
        EndDate:   r.EndDate.Format("2006-01-02"),
        Alias:     (Alias)(r),
    })
}

Решение, описанное выше, работает нормально, но дает много дублирования кода.Есть ли способ реорганизовать обе реализации MarshalJSON для использования одной и той же логики / кода?Я хорошо знаю, что Go не предлагает Generics (пока), но должен быть другой способ обойти эту проблему, верно?

1 Ответ

0 голосов
/ 21 сентября 2018

Ваш пользовательский маршалер должен быть не на структурах, а на пользовательском типе, который встраивает time.Time:

type MyTime struct {
    time.Time
}

func (t MyTime) MarshalJSON() ([]byte, error) {
    return json.Marshal(t.Format("2006-01-02"))
}

. Затем используйте этот тип везде, где хотите.

type Results struct {
    Source     string    `json:"source"`
    StartDate  MyTime
    EndDate    MyTime
}
...