mirror of https://github.com/databricks/cli.git
90 lines
2.4 KiB
Go
90 lines
2.4 KiB
Go
package jsonsaver
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/databricks/cli/libs/dyn"
|
|
)
|
|
|
|
// Marshal is a version of [json.Marshal] for [dyn.Value].
|
|
//
|
|
// Objects in the output retain the order of keys as they appear in the underlying [dyn.Value].
|
|
// The output does not escape HTML characters in strings.
|
|
func Marshal(v dyn.Value) ([]byte, error) {
|
|
return marshalNoEscape(wrap{v})
|
|
}
|
|
|
|
// MarshalIndent is a version of [json.MarshalIndent] for [dyn.Value].
|
|
//
|
|
// Objects in the output retain the order of keys as they appear in the underlying [dyn.Value].
|
|
// The output does not escape HTML characters in strings.
|
|
func MarshalIndent(v dyn.Value, prefix, indent string) ([]byte, error) {
|
|
return marshalIndentNoEscape(wrap{v}, prefix, indent)
|
|
}
|
|
|
|
// Wrapper type for [dyn.Value] to expose the [json.Marshaler] interface.
|
|
type wrap struct {
|
|
v dyn.Value
|
|
}
|
|
|
|
// MarshalJSON implements the [json.Marshaler] interface for the [dyn.Value] wrapper type.
|
|
func (w wrap) MarshalJSON() ([]byte, error) {
|
|
var buf bytes.Buffer
|
|
if err := marshalValue(&buf, w.v); err != nil {
|
|
return nil, err
|
|
}
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// marshalValue recursively writes JSON for a [dyn.Value] to the buffer.
|
|
func marshalValue(buf *bytes.Buffer, v dyn.Value) error {
|
|
switch v.Kind() {
|
|
case dyn.KindString, dyn.KindBool, dyn.KindInt, dyn.KindFloat, dyn.KindTime, dyn.KindNil:
|
|
out, err := marshalNoEscape(v.AsAny())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// The encoder writes a trailing newline, so we need to remove it
|
|
// to avoid adding extra newlines when embedding this JSON.
|
|
out = out[:len(out)-1]
|
|
buf.Write(out)
|
|
case dyn.KindMap:
|
|
buf.WriteByte('{')
|
|
for i, pair := range v.MustMap().Pairs() {
|
|
if i > 0 {
|
|
buf.WriteByte(',')
|
|
}
|
|
// Require keys to be strings.
|
|
if pair.Key.Kind() != dyn.KindString {
|
|
return fmt.Errorf("map key must be a string, got %s", pair.Key.Kind())
|
|
}
|
|
// Marshal the key
|
|
if err := marshalValue(buf, pair.Key); err != nil {
|
|
return err
|
|
}
|
|
buf.WriteByte(':')
|
|
// Marshal the value
|
|
if err := marshalValue(buf, pair.Value); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
buf.WriteByte('}')
|
|
case dyn.KindSequence:
|
|
buf.WriteByte('[')
|
|
for i, item := range v.MustSequence() {
|
|
if i > 0 {
|
|
buf.WriteByte(',')
|
|
}
|
|
if err := marshalValue(buf, item); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
buf.WriteByte(']')
|
|
default:
|
|
return fmt.Errorf("unsupported kind: %d", v.Kind())
|
|
}
|
|
return nil
|
|
}
|