There is an Unmarshaller implementation down below because of time.Unix
does only accepts seconds or nanoseconds but my data source is in milliseconds. Before asking my questions here is some code
Code:
type Platform struct {
Status CampaignStatus `json:"status" bson:"status"`
TotalBudget int `json:"total_budget" bson:"totalBudget"`
RemainingBudget int `json:"remaining_budget" bson:"remainingBudget"`
MillisecondsStartDate int64 `json:"start_date"`
StartDate time.Time `bson:"startDate"`
MillisecondsEndDate int64 `json:"end_date"`
EndDate time.Time `bson:"endDate"`
Audiance Audiance `json:"target_audiance" bson:"targetAudiance"` //typo?
Creatives Creatives `json:"creatives" bson:"Creatives"`
Insights Insights `json:"insights" bson:"insights"`
}
func (p *Platform) UnmarshalJSON(b []byte) (err error) {
p2 := struct {
Status CampaignStatus `json:"status" bson:"status"`
TotalBudget int `json:"total_budget" bson:"totalBudget"`
RemainingBudget int `json:"remaining_budget" bson:"remainingBudget"`
MillisecondsStartDate int64 `json:"start_date"`
StartDate time.Time `bson:"startDate"`
MillisecondsEndDate int64 `json:"end_date"`
EndDate time.Time `bson:"endDate"`
Audiance Audiance `json:"target_audiance" bson:"targetAudiance"` //typo?
Creatives Creatives `json:"creatives" bson:"Creatives"`
Insights Insights `json:"insights" bson:"insights"`
}{}
err = json.Unmarshal(b, &p2)
if err != nil {
return
}
p2.StartDate = time.Unix(0, p2.MillisecondsStartDate*int64(time.Millisecond/time.Nanosecond))
p2.EndDate = time.Unix(0, p2.MillisecondsEndDate*int64(time.Nanosecond/time.Microsecond))
*p = p2
return
}
My questions are
You could compose the fields that the marshaller can handle as an anonymous struct inside the Platform
struct, something like:
type platformInner struct {
Status CampaignStatus `json:"status" bson:"status"`
TotalBudget int `json:"total_budget" bson:"totalBudget"`
RemainingBudget int `json:"remaining_budget" bson:"remainingBudget"`
MillisecondsStartDate int64 `json:"start_date"`
MillisecondsEndDate int64 `json:"end_date"`
Audiance Audiance `json:"target_audiance" bson:"targetAudiance"` //typo?
Creatives Creatives `json:"creatives" bson:"Creatives"`
Insights Insights `json:"insights" bson:"insights"`
}
type Platform struct {
platformInner
StartDate time.Time `bson:"startDate"`
EndDate time.Time `bson:"endDate"`
}
And then in the custom unmarshaller, unmarshal into the nested struct, and set the other values.
func (p *Platform) UnmarshalJSON(b []byte) (err error) {
var inner platformInner
err = json.Unmarshal(b, &inner)
if err != nil {
return
}
tmp := &Platform{
innerPlatform: inner,
StartDate: time.Unix(0, inner.MillisecondsStartDate*int64(time.Millisecond/time.Nanosecond))
EndDate: time.Unix(0, inner.MillisecondsEndDate*int64(time.Nanosecond/time.Microsecond))
}
*p = tmp
return
}
Instead of duplicating the struct definition for the anonymous "p2" struct type you could alias it under a new name, such as "PlatformTemp" like so:
func (p *Platform) UnmarshalJSON(b []byte) (err error) {
type PlatformTemp Platform
var p2 PlatformTemp
err = json.Unmarshal(b, &p2)
// ...
*p = Platform(p2)
return nil
}
Since the types "Platform" and "PlatformTemp" have the same fields they can be assigned to each other with a simple cast; however, since "PlatformTemp" has no "UnmarshalJSON" method defined it will use the default unmarshaler.