garm/vendor/github.com/go-openapi/swag/jsonutils/json.go
Gabriel Adrian Samfira 47537fb8b6 Update all dependencies
Update all deps.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
2026-01-06 01:13:34 +02:00

116 lines
4 KiB
Go

// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
// SPDX-License-Identifier: Apache-2.0
package jsonutils
import (
"bytes"
"encoding/json"
"github.com/go-openapi/swag/jsonutils/adapters"
"github.com/go-openapi/swag/jsonutils/adapters/ifaces"
)
// WriteJSON marshals a data structure as JSON.
//
// The difference with [json.Marshal] is that it may check among several alternatives
// to do so.
//
// See [adapters.Registrar] for more details about how to configure
// multiple serialization alternatives.
//
// NOTE: to allow types that are [easyjson.Marshaler] s to use that route to process JSON,
// you now need to register the adapter for easyjson at runtime.
func WriteJSON(value any) ([]byte, error) {
if orderedMap, isOrdered := value.(ifaces.Ordered); isOrdered {
orderedMarshaler := adapters.OrderedMarshalAdapterFor(orderedMap)
if orderedMarshaler != nil {
defer orderedMarshaler.Redeem()
return orderedMarshaler.OrderedMarshal(orderedMap)
}
// no support found in registered adapters, fallback to the default (unordered) case
}
marshaler := adapters.MarshalAdapterFor(value)
if marshaler != nil {
defer marshaler.Redeem()
return marshaler.Marshal(value)
}
// no support found in registered adapters, fallback to the default standard library.
//
// This only happens when tinkering with the global registry of adapters, since the default handles all the above cases.
return json.Marshal(value) // Codecov ignore // this is a safeguard not easily simulated in tests
}
// ReadJSON unmarshals JSON data into a data structure.
//
// The difference with [json.Unmarshal] is that it may check among several alternatives
// to do so.
//
// See [adapters.Registrar] for more details about how to configure
// multiple serialization alternatives.
//
// NOTE: value must be a pointer.
//
// If the provided value implements [ifaces.SetOrdered], it is a considered an "ordered map" and [ReadJSON]
// will favor an adapter that supports the [ifaces.OrderedUnmarshal] feature, or fallback to
// an unordered behavior if none is found.
//
// NOTE: to allow types that are [easyjson.Unmarshaler] s to use that route to process JSON,
// you now need to register the adapter for easyjson at runtime.
func ReadJSON(data []byte, value any) error {
trimmedData := bytes.Trim(data, "\x00")
if orderedMap, isOrdered := value.(ifaces.SetOrdered); isOrdered {
// if the value is an ordered map, favors support for OrderedUnmarshal.
orderedUnmarshaler := adapters.OrderedUnmarshalAdapterFor(orderedMap)
if orderedUnmarshaler != nil {
defer orderedUnmarshaler.Redeem()
return orderedUnmarshaler.OrderedUnmarshal(trimmedData, orderedMap)
}
// no support found in registered adapters, fallback to the default (unordered) case
}
unmarshaler := adapters.UnmarshalAdapterFor(value)
if unmarshaler != nil {
defer unmarshaler.Redeem()
return unmarshaler.Unmarshal(trimmedData, value)
}
// no support found in registered adapters, fallback to the default standard library.
//
// This only happens when tinkering with the global registry of adapters, since the default handles all the above cases.
return json.Unmarshal(trimmedData, value) // Codecov ignore // this is a safeguard not easily simulated in tests
}
// FromDynamicJSON turns a go value into a properly JSON typed structure.
//
// "Dynamic JSON" refers to what you get when unmarshaling JSON into an untyped any,
// i.e. objects are represented by map[string]any, arrays by []any, and
// all numbers are represented as float64.
//
// NOTE: target must be a pointer.
//
// # Maintaining the order of keys in objects
//
// If source and target implement [ifaces.Ordered] and [ifaces.SetOrdered] respectively,
// they are considered "ordered maps" and the order of keys is maintained in the
// "jsonification" process. In that case, map[string]any values are replaced by (ordered) [JSONMapSlice] ones.
func FromDynamicJSON(source, target any) error {
b, err := WriteJSON(source)
if err != nil {
return err
}
return ReadJSON(b, target)
}