bygdata/pkg/devtodev/validation.go

54 lines
1.5 KiB
Go

package devtodev
import "fmt"
// ValidatePayload checks for required fields and common schema errors.
func ValidatePayload(payload Payload) error {
if len(payload.Reports) == 0 {
return fmt.Errorf("reports is required")
}
for ri, report := range payload.Reports {
if report.DeviceID == "" {
return fmt.Errorf("reports[%d].deviceId is required", ri)
}
if len(report.Packages) == 0 {
return fmt.Errorf("reports[%d].packages is required", ri)
}
for pi, pkg := range report.Packages {
if len(pkg.Events) == 0 {
return fmt.Errorf("reports[%d].packages[%d].events is required", ri, pi)
}
for ei, event := range pkg.Events {
code, ok := event["code"]
if !ok {
return fmt.Errorf("reports[%d].packages[%d].events[%d].code is required", ri, pi, ei)
}
if codeStr, ok := code.(string); !ok || codeStr == "" {
return fmt.Errorf("reports[%d].packages[%d].events[%d].code must be a non-empty string", ri, pi, ei)
}
ts, ok := event["timestamp"]
if !ok {
return fmt.Errorf("reports[%d].packages[%d].events[%d].timestamp is required", ri, pi, ei)
}
if !isNumber(ts) {
return fmt.Errorf("reports[%d].packages[%d].events[%d].timestamp must be a number", ri, pi, ei)
}
}
}
}
return nil
}
func isNumber(v interface{}) bool {
switch v.(type) {
case int, int8, int16, int32, int64:
return true
case uint, uint8, uint16, uint32, uint64:
return true
case float32, float64:
return true
default:
return false
}
}