func (u DeviceUplinks) MarshalJSON() ([]byte, error) {
	m := make(map[string]*LoRaUplink)
	for k, v := range u {
		m[k.String()] = v
	}
	return json.Marshal(m)
}
MarshalJSON implements json.Marshaler.
package objects
import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"strings"
	"go.thethings.network/lorawan-stack/v3/pkg/errors"
	"go.thethings.network/lorawan-stack/v3/pkg/types"
)
type DeviceUplinkResponse struct {
	Result ExtendedUplinkResponse `json:"result"`
	Error  string                 `json:"error"`
}
type DeviceUplinkResponses map[EUI]DeviceUplinkResponse
func (d DeviceUplinkResponses) UnmarshalJSON(b []byte) error {
	m := make(map[string]DeviceUplinkResponse)
	err := json.Unmarshal(b, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		eui, err := toEUI(k)
		if err != nil {
			return err
		}
		d[eui] = v
	}
	return nil
}
type PositionSolutionType uint8
const (
	GNSSPositionSolutionType PositionSolutionType = iota
	WiFiPositionSolutionType
	UnknownPositionSolutionType
)
type PositionSolution struct {
	Algorithm PositionSolutionType `json:"algorithm_type"`
	LLH       []float64            `json:"llh"`
	Accuracy  float64              `json:"accuracy"`
}
const (
	gnssPositionSolutionType    = "gnss"
	wifiPositionSolutionType    = "wifi"
	unknownPositionSolutionType = "unknown"
)
func (t PositionSolutionType) MarshalJSON() ([]byte, error) {
	var tp string
	switch t {
	case GNSSPositionSolutionType:
		tp = gnssPositionSolutionType
	case WiFiPositionSolutionType:
		tp = wifiPositionSolutionType
	default:
		tp = unknownPositionSolutionType
	}
	return json.Marshal(tp)
}
func (t *PositionSolutionType) UnmarshalJSON(b []byte) error {
	var tp string
	err := json.Unmarshal(b, &tp)
	if err != nil {
		return err
	}
	switch tp {
	case gnssPositionSolutionType:
		*t = GNSSPositionSolutionType
	case wifiPositionSolutionType:
		*t = WiFiPositionSolutionType
	default:
		*t = UnknownPositionSolutionType
	}
	return nil
}
func (t PositionSolutionType) String() string {
	switch t {
	case GNSSPositionSolutionType:
		return gnssPositionSolutionType
	case WiFiPositionSolutionType:
		return wifiPositionSolutionType
	default:
		return unknownPositionSolutionType
	}
}
type StreamRecord struct {
	Offset uint32
	Data   Hex
}
func (r StreamRecord) MarshalJSON() ([]byte, error) {
	return json.Marshal([]interface{}{r.Offset, r.Data})
}
var errInvalidStreamRecord = errors.DefineCorruption("invalid_stream_record", "invalid stream record")
func (r *StreamRecord) UnmarshalJSON(b []byte) error {
	raw := make([]json.RawMessage, 0, 2)
	if err := json.Unmarshal(b, &raw); err != nil {
		return err
	}
	if len(raw) != 2 {
		return errInvalidStreamRecord.New()
	}
	if err := json.Unmarshal(raw[0], &r.Offset); err != nil {
		return err
	}
	return json.Unmarshal(raw[1], &r.Data)
}
type UplinkResponse struct {
	Downlink      *LoRaDnlink       `json:"dnlink"`
	StreamRecords []StreamRecord    `json:"stream_records"`
	Position      *PositionSolution `json:"position_solution"`
}
type ExtendedUplinkResponse struct {
	UplinkResponse
	Raw *json.RawMessage
}
func (r ExtendedUplinkResponse) MarshalJSON() ([]byte, error) {
	if r.Raw != nil {
		return r.Raw.MarshalJSON()
	}
	return json.Marshal(r.UplinkResponse)
}
func (r *ExtendedUplinkResponse) UnmarshalJSON(b []byte) error {
	r.Raw = &json.RawMessage{}
	if err := r.Raw.UnmarshalJSON(b); err != nil {
		return err
	}
	return json.Unmarshal(b, &r.UplinkResponse)
}
type DeviceUplinks map[EUI]*LoRaUplink