Generate UnmarshalJSON to handle emptyStringInt types
This commit changes the code generator to generate a `UnmarshalJSON` for each struct, so that if unmarshalled it properly handles UniFis varying integer values via the `emptyStringInt` type. Structs not including a field of `int` type will still have the function generated, but it will effectively do nothing. Fixes #18
This commit is contained in:
committed by
Paul Tyng
parent
c5ff8c8593
commit
4aed7d703d
@@ -5,13 +5,15 @@ package unifi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// just to fix compile issues with the import
|
||||
var (
|
||||
_ fmt.Formatter
|
||||
_ context.Context
|
||||
_ fmt.Formatter
|
||||
_ json.Marshaler
|
||||
)
|
||||
|
||||
type Device struct {
|
||||
@@ -81,6 +83,35 @@ type Device struct {
|
||||
Y float64 `json:"y,omitempty"`
|
||||
}
|
||||
|
||||
func (dst *Device) UnmarshalJSON(b []byte) error {
|
||||
type Alias Device
|
||||
aux := &struct {
|
||||
LcmBrightness emptyStringInt `json:"lcm_brightness"`
|
||||
LcmIDleTimeout emptyStringInt `json:"lcm_idle_timeout"`
|
||||
LedOverrideColorBrightness emptyStringInt `json:"led_override_color_brightness"`
|
||||
LteSimPin emptyStringInt `json:"lte_sim_pin"`
|
||||
LteSoftLimit emptyStringInt `json:"lte_soft_limit"`
|
||||
Volume emptyStringInt `json:"volume"`
|
||||
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
dst.LcmBrightness = int(aux.LcmBrightness)
|
||||
dst.LcmIDleTimeout = int(aux.LcmIDleTimeout)
|
||||
dst.LedOverrideColorBrightness = int(aux.LedOverrideColorBrightness)
|
||||
dst.LteSimPin = int(aux.LteSimPin)
|
||||
dst.LteSoftLimit = int(aux.LteSoftLimit)
|
||||
dst.Volume = int(aux.Volume)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceConfigNetwork struct {
|
||||
BondingEnabled bool `json:"bonding_enabled,omitempty"`
|
||||
DNS1 string `json:"dns1,omitempty"` // ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$|^$
|
||||
@@ -92,11 +123,43 @@ type DeviceConfigNetwork struct {
|
||||
Type string `json:"type,omitempty"` // dhcp|static
|
||||
}
|
||||
|
||||
func (dst *DeviceConfigNetwork) UnmarshalJSON(b []byte) error {
|
||||
type Alias DeviceConfigNetwork
|
||||
aux := &struct {
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceEthernetOverrides struct {
|
||||
Ifname string `json:"ifname,omitempty"` // eth[0-9]{1,2}
|
||||
NetworkGroup string `json:"networkgroup,omitempty"` // LAN[2-8]?|WAN[2]?
|
||||
}
|
||||
|
||||
func (dst *DeviceEthernetOverrides) UnmarshalJSON(b []byte) error {
|
||||
type Alias DeviceEthernetOverrides
|
||||
aux := &struct {
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceOutletOverrides struct {
|
||||
CycleEnabled bool `json:"cycle_enabled,omitempty"`
|
||||
Index int `json:"index,omitempty"`
|
||||
@@ -104,6 +167,25 @@ type DeviceOutletOverrides struct {
|
||||
RelayState bool `json:"relay_state,omitempty"`
|
||||
}
|
||||
|
||||
func (dst *DeviceOutletOverrides) UnmarshalJSON(b []byte) error {
|
||||
type Alias DeviceOutletOverrides
|
||||
aux := &struct {
|
||||
Index emptyStringInt `json:"index"`
|
||||
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
dst.Index = int(aux.Index)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DevicePortOverrides struct {
|
||||
AggregateNumPorts int `json:"aggregate_num_ports,omitempty"` // [2-6]
|
||||
Autoneg bool `json:"autoneg,omitempty"`
|
||||
@@ -141,6 +223,55 @@ type DevicePortOverrides struct {
|
||||
StpPortMode bool `json:"stp_port_mode,omitempty"`
|
||||
}
|
||||
|
||||
func (dst *DevicePortOverrides) UnmarshalJSON(b []byte) error {
|
||||
type Alias DevicePortOverrides
|
||||
aux := &struct {
|
||||
AggregateNumPorts emptyStringInt `json:"aggregate_num_ports"`
|
||||
Dot1XIDleTimeout emptyStringInt `json:"dot1x_idle_timeout"`
|
||||
EgressRateLimitKbps emptyStringInt `json:"egress_rate_limit_kbps"`
|
||||
MirrorPortIDX emptyStringInt `json:"mirror_port_idx"`
|
||||
PortIDX emptyStringInt `json:"port_idx"`
|
||||
PriorityQueue1Level emptyStringInt `json:"priority_queue1_level"`
|
||||
PriorityQueue2Level emptyStringInt `json:"priority_queue2_level"`
|
||||
PriorityQueue3Level emptyStringInt `json:"priority_queue3_level"`
|
||||
PriorityQueue4Level emptyStringInt `json:"priority_queue4_level"`
|
||||
Speed emptyStringInt `json:"speed"`
|
||||
StormctrlBroadcastastLevel emptyStringInt `json:"stormctrl_bcast_level"`
|
||||
StormctrlBroadcastastRate emptyStringInt `json:"stormctrl_bcast_rate"`
|
||||
StormctrlMcastLevel emptyStringInt `json:"stormctrl_mcast_level"`
|
||||
StormctrlMcastRate emptyStringInt `json:"stormctrl_mcast_rate"`
|
||||
StormctrlUcastLevel emptyStringInt `json:"stormctrl_ucast_level"`
|
||||
StormctrlUcastRate emptyStringInt `json:"stormctrl_ucast_rate"`
|
||||
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
dst.AggregateNumPorts = int(aux.AggregateNumPorts)
|
||||
dst.Dot1XIDleTimeout = int(aux.Dot1XIDleTimeout)
|
||||
dst.EgressRateLimitKbps = int(aux.EgressRateLimitKbps)
|
||||
dst.MirrorPortIDX = int(aux.MirrorPortIDX)
|
||||
dst.PortIDX = int(aux.PortIDX)
|
||||
dst.PriorityQueue1Level = int(aux.PriorityQueue1Level)
|
||||
dst.PriorityQueue2Level = int(aux.PriorityQueue2Level)
|
||||
dst.PriorityQueue3Level = int(aux.PriorityQueue3Level)
|
||||
dst.PriorityQueue4Level = int(aux.PriorityQueue4Level)
|
||||
dst.Speed = int(aux.Speed)
|
||||
dst.StormctrlBroadcastastLevel = int(aux.StormctrlBroadcastastLevel)
|
||||
dst.StormctrlBroadcastastRate = int(aux.StormctrlBroadcastastRate)
|
||||
dst.StormctrlMcastLevel = int(aux.StormctrlMcastLevel)
|
||||
dst.StormctrlMcastRate = int(aux.StormctrlMcastRate)
|
||||
dst.StormctrlUcastLevel = int(aux.StormctrlUcastLevel)
|
||||
dst.StormctrlUcastRate = int(aux.StormctrlUcastRate)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceRadioTable struct {
|
||||
AntennaGain int `json:"antenna_gain,omitempty"` // ^-?([0-9]|[1-9][0-9])
|
||||
AntennaID int `json:"antenna_id,omitempty"` // -1|[0-9]
|
||||
@@ -161,17 +292,85 @@ type DeviceRadioTable struct {
|
||||
VwireEnabled bool `json:"vwire_enabled,omitempty"`
|
||||
}
|
||||
|
||||
func (dst *DeviceRadioTable) UnmarshalJSON(b []byte) error {
|
||||
type Alias DeviceRadioTable
|
||||
aux := &struct {
|
||||
AntennaGain emptyStringInt `json:"antenna_gain"`
|
||||
AntennaID emptyStringInt `json:"antenna_id"`
|
||||
BackupChannel emptyStringInt `json:"backup_channel"`
|
||||
Channel emptyStringInt `json:"channel"`
|
||||
Maxsta emptyStringInt `json:"maxsta"`
|
||||
MinRssi emptyStringInt `json:"min_rssi"`
|
||||
SensLevel emptyStringInt `json:"sens_level"`
|
||||
TxPower emptyStringInt `json:"tx_power"`
|
||||
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
dst.AntennaGain = int(aux.AntennaGain)
|
||||
dst.AntennaID = int(aux.AntennaID)
|
||||
dst.BackupChannel = int(aux.BackupChannel)
|
||||
dst.Channel = int(aux.Channel)
|
||||
dst.Maxsta = int(aux.Maxsta)
|
||||
dst.MinRssi = int(aux.MinRssi)
|
||||
dst.SensLevel = int(aux.SensLevel)
|
||||
dst.TxPower = int(aux.TxPower)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceRpsOverride struct {
|
||||
PowerManagementMode string `json:"power_management_mode,omitempty"` // dynamic|static
|
||||
RpsPortTable []DeviceRpsPortTable `json:"rps_port_table,omitempty"`
|
||||
}
|
||||
|
||||
func (dst *DeviceRpsOverride) UnmarshalJSON(b []byte) error {
|
||||
type Alias DeviceRpsOverride
|
||||
aux := &struct {
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceRpsPortTable struct {
|
||||
Name string `json:"name,omitempty"` // .{0,32}
|
||||
PortIDX int `json:"port_idx,omitempty"` // [1-6]
|
||||
PortMode string `json:"port_mode,omitempty"` // auto|force_active|manual|disabled
|
||||
}
|
||||
|
||||
func (dst *DeviceRpsPortTable) UnmarshalJSON(b []byte) error {
|
||||
type Alias DeviceRpsPortTable
|
||||
aux := &struct {
|
||||
PortIDX emptyStringInt `json:"port_idx"`
|
||||
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
dst.PortIDX = int(aux.PortIDX)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceWLANOverrides struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Name string `json:"name,omitempty"` // .{1,32}
|
||||
@@ -185,6 +384,25 @@ type DeviceWLANOverrides struct {
|
||||
XPassphrase string `json:"x_passphrase,omitempty"` // [\x20-\x7E]{8,63}|[0-9a-fA-F]{64}
|
||||
}
|
||||
|
||||
func (dst *DeviceWLANOverrides) UnmarshalJSON(b []byte) error {
|
||||
type Alias DeviceWLANOverrides
|
||||
aux := &struct {
|
||||
VLAN emptyStringInt `json:"vlan"`
|
||||
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(dst),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &aux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal alias: %w", err)
|
||||
}
|
||||
dst.VLAN = int(aux.VLAN)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) listDevice(ctx context.Context, site string) ([]Device, error) {
|
||||
var respBody struct {
|
||||
Meta meta `json:"meta"`
|
||||
|
||||
Reference in New Issue
Block a user