Fixing unmarshalling of numberOrString
New unmarshalling rules for fields which could be numeric or string values were not properly typecasted upon being deserialized. Cleaned up the api template file and moved custom unmarshalling type logic into go code out of the template.
This commit is contained in:
committed by
Paul Tyng
parent
4ab4036985
commit
fbed685c37
@@ -2,22 +2,19 @@
|
|||||||
|
|
||||||
{{ define "field" }}
|
{{ define "field" }}
|
||||||
{{ .FieldName }} {{ if .IsArray }}[]{{end}}{{ .FieldType }} `json:"{{ .JSONName }}{{ if .OmitEmpty }},omitempty{{ end }}"` {{ if .FieldValidation }}// {{ .FieldValidation }}{{ end }} {{- end }}
|
{{ .FieldName }} {{ if .IsArray }}[]{{end}}{{ .FieldType }} `json:"{{ .JSONName }}{{ if .OmitEmpty }},omitempty{{ end }}"` {{ if .FieldValidation }}// {{ .FieldValidation }}{{ end }} {{- end }}
|
||||||
{{ define "field-emptyStringInt" }}
|
{{ define "field-customUnmarshalType" }}
|
||||||
{{- if ne .FieldType "int" }}{{else}}
|
{{- if eq .CustomUnmarshalType "" }}{{else}}
|
||||||
{{ .FieldName }} {{ if .IsArray }}[]{{end}}emptyStringInt `json:"{{ .JSONName }}{{ if .OmitEmpty }}{{ end }}"`{{ end }} {{- end }}
|
{{ .FieldName }} {{ if .IsArray }}[]{{end}}{{ .CustomUnmarshalType }} `json:"{{ .JSONName }}{{ if .OmitEmpty }}{{ end }}"`{{ end }} {{- end }}
|
||||||
{{ define "field-numberOrString" }}
|
|
||||||
{{- /* this is kind of a hack, probably a better way to do this when looking at the normalized validation */ -}}
|
|
||||||
{{- if and (eq .FieldType "string") (or (eq .JSONName "channel") (eq .JSONName "backup_channel") (eq .JSONName "tx_power")) }}
|
|
||||||
{{ .FieldName }} {{ if .IsArray }}[]{{end}}numberOrString `json:"{{ .JSONName }}{{ if .OmitEmpty }}{{ end }}"`{{ end }} {{- end }}
|
|
||||||
{{ define "typecast" }}
|
{{ define "typecast" }}
|
||||||
{{- if eq .FieldType "int" }}{{- if .IsArray }}
|
{{- if eq .CustomUnmarshalType "" }}{{else}}
|
||||||
dst.{{ .FieldName }}= make([]int, len(aux.{{ .FieldName }}))
|
{{- if .IsArray }}
|
||||||
for i, v := range aux.{{ .FieldName }} {
|
dst.{{ .FieldName }}= make([]{{ .FieldType }}, len(aux.{{ .FieldName }}))
|
||||||
dst.{{ .FieldName }}[i] = int(v)
|
for i, v := range aux.{{ .FieldName }} {
|
||||||
}
|
dst.{{ .FieldName }}[i] = {{ .FieldType }}(v)
|
||||||
{{- else }}
|
}
|
||||||
dst.{{ .FieldName }} = int(aux.{{ .FieldName }})
|
{{- else }}
|
||||||
{{- end }}{{- end }}{{- end }}
|
dst.{{ .FieldName }} = {{ .FieldType }}(aux.{{ .FieldName }})
|
||||||
|
{{- end }}{{- end }}{{- end }}
|
||||||
{{ define "field-embed" }}
|
{{ define "field-embed" }}
|
||||||
{{ .FieldName }} {{ if .IsArray }}[]{{end}}{{ if not .Fields }}{{ .FieldType }}{{ else }}struct {
|
{{ .FieldName }} {{ if .IsArray }}[]{{end}}{{ if not .Fields }}{{ .FieldType }}{{ else }}struct {
|
||||||
{{ range $fk, $fv := .Fields }}{{ if not $fv }}
|
{{ range $fk, $fv := .Fields }}{{ if not $fv }}
|
||||||
@@ -58,8 +55,8 @@ type {{ $k }} struct {
|
|||||||
func (dst *{{ $k }}) UnmarshalJSON(b []byte) error {
|
func (dst *{{ $k }}) UnmarshalJSON(b []byte) error {
|
||||||
type Alias {{ $k }}
|
type Alias {{ $k }}
|
||||||
aux := &struct {
|
aux := &struct {
|
||||||
{{- range $fk, $fv := $v.Fields }}{{ if not $fv }}
|
{{- range $fk, $fv := $v.Fields }}{{ if not $fv }}
|
||||||
{{- else }}{{- template "field-emptyStringInt" $fv }}{{- template "field-numberOrString" $fv }}{{ end }}{{- end }}
|
{{- else }}{{- template "field-customUnmarshalType" $fv }}{{ end }}{{- end }}
|
||||||
|
|
||||||
*Alias
|
*Alias
|
||||||
}{
|
}{
|
||||||
@@ -71,8 +68,8 @@ func (dst *{{ $k }}) UnmarshalJSON(b []byte) error {
|
|||||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
{{- range $fk, $fv := $v.Fields }}{{ if not $fv }}
|
{{- range $fk, $fv := $v.Fields }}{{ if not $fv }}
|
||||||
{{- else }}{{- template "typecast" $fv }}{{ end }}{{ end }}
|
{{- else }}{{- template "typecast" $fv }}{{ end }}{{ end }}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,13 +98,14 @@ type Resource struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FieldInfo struct {
|
type FieldInfo struct {
|
||||||
FieldName string
|
FieldName string
|
||||||
JSONName string
|
JSONName string
|
||||||
FieldType string
|
FieldType string
|
||||||
FieldValidation string
|
FieldValidation string
|
||||||
OmitEmpty bool
|
OmitEmpty bool
|
||||||
IsArray bool
|
IsArray bool
|
||||||
Fields map[string]*FieldInfo
|
Fields map[string]*FieldInfo
|
||||||
|
CustomUnmarshalType string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewResource(structName string, resourcePath string) *Resource {
|
func NewResource(structName string, resourcePath string) *Resource {
|
||||||
@@ -278,6 +279,16 @@ func main() {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
case "ChannelPlan":
|
||||||
|
resource.FieldProcessor = func(name string, f *FieldInfo) error {
|
||||||
|
switch name {
|
||||||
|
case "Channel", "BackupChannel", "TxPower":
|
||||||
|
if f.FieldType == "string" {
|
||||||
|
f.CustomUnmarshalType = "numberOrString"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
case "Device":
|
case "Device":
|
||||||
resource.FieldProcessor = func(name string, f *FieldInfo) error {
|
resource.FieldProcessor = func(name string, f *FieldInfo) error {
|
||||||
switch name {
|
switch name {
|
||||||
@@ -285,6 +296,11 @@ func main() {
|
|||||||
f.FieldType = "float64"
|
f.FieldType = "float64"
|
||||||
case "StpPriority", "Ht":
|
case "StpPriority", "Ht":
|
||||||
f.FieldType = "string"
|
f.FieldType = "string"
|
||||||
|
f.CustomUnmarshalType = ""
|
||||||
|
case "Channel", "BackupChannel", "TxPower":
|
||||||
|
if f.FieldType == "string" {
|
||||||
|
f.CustomUnmarshalType = "numberOrString"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.OmitEmpty = true
|
f.OmitEmpty = true
|
||||||
@@ -294,6 +310,7 @@ func main() {
|
|||||||
resource.FieldProcessor = func(name string, f *FieldInfo) error {
|
resource.FieldProcessor = func(name string, f *FieldInfo) error {
|
||||||
if strings.HasSuffix(name, "Timeout") && name != "ArpCacheTimeout" {
|
if strings.HasSuffix(name, "Timeout") && name != "ArpCacheTimeout" {
|
||||||
f.FieldType = "int"
|
f.FieldType = "int"
|
||||||
|
f.CustomUnmarshalType = "emptyStringInt"
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -304,6 +321,7 @@ func main() {
|
|||||||
f.FieldType = "bool"
|
f.FieldType = "bool"
|
||||||
case "LastSeen":
|
case "LastSeen":
|
||||||
f.FieldType = "int"
|
f.FieldType = "int"
|
||||||
|
f.CustomUnmarshalType = "emptyStringInt"
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -416,6 +434,7 @@ func (r *Resource) fieldInfoFromValidation(name string, validation interface{})
|
|||||||
|
|
||||||
omitEmpty = true
|
omitEmpty = true
|
||||||
fieldInfo, err = NewFieldInfo(fieldName, name, "int", fieldValidation, omitEmpty, false), nil
|
fieldInfo, err = NewFieldInfo(fieldName, name, "int", fieldValidation, omitEmpty, false), nil
|
||||||
|
fieldInfo.CustomUnmarshalType = "emptyStringInt"
|
||||||
return fieldInfo, r.FieldProcessor(fieldName, fieldInfo)
|
return fieldInfo, r.FieldProcessor(fieldName, fieldInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,9 @@ func (dst *ChannelPlanRadioTable) UnmarshalJSON(b []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||||
}
|
}
|
||||||
|
dst.BackupChannel = string(aux.BackupChannel)
|
||||||
|
dst.Channel = string(aux.Channel)
|
||||||
|
dst.TxPower = string(aux.TxPower)
|
||||||
dst.Width = int(aux.Width)
|
dst.Width = int(aux.Width)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -315,9 +315,12 @@ func (dst *DeviceRadioTable) UnmarshalJSON(b []byte) error {
|
|||||||
}
|
}
|
||||||
dst.AntennaGain = int(aux.AntennaGain)
|
dst.AntennaGain = int(aux.AntennaGain)
|
||||||
dst.AntennaID = int(aux.AntennaID)
|
dst.AntennaID = int(aux.AntennaID)
|
||||||
|
dst.BackupChannel = string(aux.BackupChannel)
|
||||||
|
dst.Channel = string(aux.Channel)
|
||||||
dst.Maxsta = int(aux.Maxsta)
|
dst.Maxsta = int(aux.Maxsta)
|
||||||
dst.MinRssi = int(aux.MinRssi)
|
dst.MinRssi = int(aux.MinRssi)
|
||||||
dst.SensLevel = int(aux.SensLevel)
|
dst.SensLevel = int(aux.SensLevel)
|
||||||
|
dst.TxPower = string(aux.TxPower)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user