Füge benutzerdefinierte JSON-Unmarshaling-Logik für Zeitfelder hinzu; verbessere die Handhabung von optionalen Zeitwerten

This commit is contained in:
Gregor Schulte
2026-02-17 12:53:56 +01:00
parent 79caa168db
commit 727eba0e5e
2 changed files with 240 additions and 25 deletions

View File

@@ -46,24 +46,24 @@ func (s *BlockTypesService) GetBySlug(ctx context.Context, slug string) (*models
// List retrieves block types with optional filtering. // List retrieves block types with optional filtering.
func (s *BlockTypesService) List(ctx context.Context, filter *models.BlockTypeFilter, offset, limit int) ([]models.BlockType, error) { func (s *BlockTypesService) List(ctx context.Context, filter *models.BlockTypeFilter, offset, limit int) ([]models.BlockType, error) {
type nameFilter struct { type nameFilter struct {
Like *string `json:"like_,omitempty"` Like *string `json:"like,omitempty"`
} }
type slugFilter struct { type slugFilter struct {
Any []string `json:"any_,omitempty"` Any []string `json:"any,omitempty"`
} }
type blockTypeFilterCriteria struct { type blockTypeFilterCriteria struct {
Name *nameFilter `json:"name,omitempty"` Name *nameFilter `json:"name,omitempty"`
Slug *slugFilter `json:"slug,omitempty"` Slug *slugFilter `json:"slug,omitempty"`
} }
type capabilitiesFilter struct { type capabilitiesFilter struct {
All []string `json:"all_,omitempty"` All []string `json:"all,omitempty"`
} }
type blockSchemaFilterCriteria struct { type blockSchemaFilterCriteria struct {
Capabilities *capabilitiesFilter `json:"block_capabilities,omitempty"` Capabilities *capabilitiesFilter `json:"block_capabilities,omitempty"`
} }
type request struct { type request struct {
BlockTypes *blockTypeFilterCriteria `json:"block_types,omitempty"` BlockTypes *blockTypeFilterCriteria `json:"block_types,omitempty"`
BlockSchemas *blockSchemaFilterCriteria `json:"block_schemas,omitempty"` BlockSchemas *blockSchemaFilterCriteria `json:"block_schemas,omitempty"`
Offset int `json:"offset,omitempty"` Offset int `json:"offset,omitempty"`
Limit int `json:"limit,omitempty"` Limit int `json:"limit,omitempty"`
} }

View File

@@ -405,36 +405,251 @@ type BlockDocumentFilter struct {
IsAnonymous *bool // Filter by anonymity IsAnonymous *bool // Filter by anonymity
} }
// parseOptionalTime parses a time string, returning nil for empty strings.
// Supports RFC3339Nano and RFC3339 formats used by the Prefect API.
func parseOptionalTime(s string) (*time.Time, error) {
if s == "" {
return nil, nil
}
t, err := time.Parse(time.RFC3339Nano, s)
if err != nil {
t, err = time.Parse(time.RFC3339, s)
if err != nil {
return nil, err
}
}
return &t, nil
}
// optTime handles JSON unmarshaling of nullable time fields that may be
// represented as empty strings or JSON null by the Prefect API.
type optTime struct {
V *time.Time
}
func (o *optTime) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
o.V = nil
return nil
}
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
v, err := parseOptionalTime(s)
if err != nil {
return err
}
o.V = v
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields. // UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (f *Flow) UnmarshalJSON(data []byte) error { func (f *Flow) UnmarshalJSON(data []byte) error {
type Alias Flow type Alias Flow
aux := &struct { aux := &struct {
Created string `json:"created"` Created optTime `json:"created"`
Updated string `json:"updated"` Updated optTime `json:"updated"`
*Alias *Alias
}{ }{
Alias: (*Alias)(f), Alias: (*Alias)(f),
} }
if err := json.Unmarshal(data, aux); err != nil {
if err := json.Unmarshal(data, &aux); err != nil {
return err return err
} }
f.Created = aux.Created.V
if aux.Created != "" { f.Updated = aux.Updated.V
t, err := time.Parse(time.RFC3339, aux.Created) return nil
if err != nil { }
return err
} // UnmarshalJSON implements custom JSON unmarshaling for time fields.
f.Created = &t func (fr *FlowRun) UnmarshalJSON(data []byte) error {
} type Alias FlowRun
aux := &struct {
if aux.Updated != "" { Created optTime `json:"created"`
t, err := time.Parse(time.RFC3339, aux.Updated) Updated optTime `json:"updated"`
if err != nil { ExpectedStartTime optTime `json:"expected_start_time"`
return err NextScheduledStartTime optTime `json:"next_scheduled_start_time"`
} StartTime optTime `json:"start_time"`
f.Updated = &t EndTime optTime `json:"end_time"`
} *Alias
}{
Alias: (*Alias)(fr),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
fr.Created = aux.Created.V
fr.Updated = aux.Updated.V
fr.ExpectedStartTime = aux.ExpectedStartTime.V
fr.NextScheduledStartTime = aux.NextScheduledStartTime.V
fr.StartTime = aux.StartTime.V
fr.EndTime = aux.EndTime.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (d *Deployment) UnmarshalJSON(data []byte) error {
type Alias Deployment
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
*Alias
}{
Alias: (*Alias)(d),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
d.Created = aux.Created.V
d.Updated = aux.Updated.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (tr *TaskRun) UnmarshalJSON(data []byte) error {
type Alias TaskRun
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
StartTime optTime `json:"start_time"`
EndTime optTime `json:"end_time"`
*Alias
}{
Alias: (*Alias)(tr),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
tr.Created = aux.Created.V
tr.Updated = aux.Updated.V
tr.StartTime = aux.StartTime.V
tr.EndTime = aux.EndTime.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (wp *WorkPool) UnmarshalJSON(data []byte) error {
type Alias WorkPool
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
*Alias
}{
Alias: (*Alias)(wp),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
wp.Created = aux.Created.V
wp.Updated = aux.Updated.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (wq *WorkQueue) UnmarshalJSON(data []byte) error {
type Alias WorkQueue
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
*Alias
}{
Alias: (*Alias)(wq),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
wq.Created = aux.Created.V
wq.Updated = aux.Updated.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (v *Variable) UnmarshalJSON(data []byte) error {
type Alias Variable
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
*Alias
}{
Alias: (*Alias)(v),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
v.Created = aux.Created.V
v.Updated = aux.Updated.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (l *Log) UnmarshalJSON(data []byte) error {
type Alias Log
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
*Alias
}{
Alias: (*Alias)(l),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
l.Created = aux.Created.V
l.Updated = aux.Updated.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (bt *BlockType) UnmarshalJSON(data []byte) error {
type Alias BlockType
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
*Alias
}{
Alias: (*Alias)(bt),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
bt.Created = aux.Created.V
bt.Updated = aux.Updated.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (bs *BlockSchema) UnmarshalJSON(data []byte) error {
type Alias BlockSchema
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
*Alias
}{
Alias: (*Alias)(bs),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
bs.Created = aux.Created.V
bs.Updated = aux.Updated.V
return nil
}
// UnmarshalJSON implements custom JSON unmarshaling for time fields.
func (bd *BlockDocument) UnmarshalJSON(data []byte) error {
type Alias BlockDocument
aux := &struct {
Created optTime `json:"created"`
Updated optTime `json:"updated"`
*Alias
}{
Alias: (*Alias)(bd),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
bd.Created = aux.Created.V
bd.Updated = aux.Updated.V
return nil return nil
} }