Refactor normalizers: dedupe JSON decode + event finalize

Add shared normalizer helpers to centralize payload extraction, JSON decoding,
and event finalization/validation.

Refactor NWS, Open-Meteo, and OpenWeather observation normalizers to use the
shared spine, removing repeated boilerplate while preserving provider-specific
mapping logic.
This commit is contained in:
2026-01-15 10:36:18 -06:00
parent e92577c30e
commit 8968b6bdcd
5 changed files with 118 additions and 90 deletions

View File

@@ -3,7 +3,6 @@ package openweather
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
@@ -41,35 +40,12 @@ func (ObservationNormalizer) Match(e event.Event) bool {
func (ObservationNormalizer) Normalize(ctx context.Context, in event.Event) (*event.Event, error) {
_ = ctx // normalization is pure/CPU; keep ctx for future expensive steps
rawBytes, err := normcommon.PayloadBytes(in)
if err != nil {
return nil, fmt.Errorf("openweather observation normalize: %w", err)
}
var parsed owmResponse
if err := json.Unmarshal(rawBytes, &parsed); err != nil {
return nil, fmt.Errorf("openweather observation normalize: decode raw payload: %w", err)
}
obs, effectiveAt, err := buildObservation(parsed)
if err != nil {
return nil, err
}
out := in
out.Schema = standards.SchemaWeatherObservationV1
out.Payload = obs
// EffectiveAt is optional; for observations it is naturally the observation timestamp.
if !effectiveAt.IsZero() {
t := effectiveAt.UTC()
out.EffectiveAt = &t
}
if err := out.Validate(); err != nil {
return nil, err
}
return &out, nil
return normcommon.NormalizeJSON(
in,
"openweather observation",
standards.SchemaWeatherObservationV1,
buildObservation,
)
}
// buildObservation contains the domain mapping logic (provider -> canonical model).