From a85e600fb21467c6926e5f04de2ac790272e65d0 Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Sat, 6 Jun 2015 10:05:41 +0200 Subject: [PATCH] Validate LabelName/LabelSet on JSON unmarshaling. --- model/labelname.go | 14 ++++++++++++++ model/labelset.go | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/model/labelname.go b/model/labelname.go index 7efbd9f..ed6915c 100644 --- a/model/labelname.go +++ b/model/labelname.go @@ -14,6 +14,7 @@ package model import ( + "encoding/json" "fmt" "regexp" "strings" @@ -81,6 +82,19 @@ func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error { return nil } +// UnmarshalJSON implements the json.Unmarshaler interface. +func (ln *LabelName) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + if !LabelNameRE.MatchString(s) { + return fmt.Errorf("%q is not a valid label name", s) + } + *ln = LabelName(s) + return nil +} + // LabelNames is a sortable LabelName slice. In implements sort.Interface. type LabelNames []LabelName diff --git a/model/labelset.go b/model/labelset.go index b1b54fb..382ab62 100644 --- a/model/labelset.go +++ b/model/labelset.go @@ -14,6 +14,7 @@ package model import ( + "encoding/json" "fmt" "sort" "strings" @@ -62,3 +63,21 @@ func (l LabelSet) MergeFromMetric(m Metric) { l[k] = v } } + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (l *LabelSet) UnmarshalJSON(b []byte) error { + var m map[LabelName]LabelValue + if err := json.Unmarshal(b, &m); err != nil { + return err + } + // encoding/json only unmarshals maps of the form map[string]T. It treats + // LabelName as a string and does not call its UnmarshalJSON method. + // Thus, we have to replicate the behavior here. + for ln := range m { + if !LabelNameRE.MatchString(string(ln)) { + return fmt.Errorf("%q is not a valid label name", ln) + } + } + *l = LabelSet(m) + return nil +}