166 lines
3.8 KiB
Go
166 lines
3.8 KiB
Go
package packagejson
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/collections"
|
|
"github.com/go-json-experiment/json"
|
|
"github.com/go-json-experiment/json/jsontext"
|
|
)
|
|
|
|
type JSONValueType int8
|
|
|
|
const (
|
|
JSONValueTypeNotPresent JSONValueType = iota
|
|
JSONValueTypeNull
|
|
JSONValueTypeString
|
|
JSONValueTypeNumber
|
|
JSONValueTypeBoolean
|
|
JSONValueTypeArray
|
|
JSONValueTypeObject
|
|
)
|
|
|
|
func (t JSONValueType) String() string {
|
|
switch t {
|
|
case JSONValueTypeNull:
|
|
return "null"
|
|
case JSONValueTypeString:
|
|
return "string"
|
|
case JSONValueTypeNumber:
|
|
return "number"
|
|
case JSONValueTypeBoolean:
|
|
return "boolean"
|
|
case JSONValueTypeArray:
|
|
return "array"
|
|
case JSONValueTypeObject:
|
|
return "object"
|
|
default:
|
|
return fmt.Sprintf("unknown(%d)", t)
|
|
}
|
|
}
|
|
|
|
type JSONValue struct {
|
|
Type JSONValueType
|
|
Value any
|
|
}
|
|
|
|
func (v *JSONValue) IsFalsy() bool {
|
|
switch v.Type {
|
|
case JSONValueTypeNotPresent, JSONValueTypeNull:
|
|
return true
|
|
case JSONValueTypeString:
|
|
return v.Value == ""
|
|
case JSONValueTypeNumber:
|
|
return v.Value == 0
|
|
case JSONValueTypeBoolean:
|
|
return !v.Value.(bool)
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func (v JSONValue) AsObject() *collections.OrderedMap[string, JSONValue] {
|
|
if v.Type != JSONValueTypeObject {
|
|
panic(fmt.Sprintf("expected object, got %v", v.Type))
|
|
}
|
|
return v.Value.(*collections.OrderedMap[string, JSONValue])
|
|
}
|
|
|
|
func (v JSONValue) AsArray() []JSONValue {
|
|
if v.Type != JSONValueTypeArray {
|
|
panic(fmt.Sprintf("expected array, got %v", v.Type))
|
|
}
|
|
return v.Value.([]JSONValue)
|
|
}
|
|
|
|
var _ json.UnmarshalerFrom = (*JSONValue)(nil)
|
|
|
|
func (v *JSONValue) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
|
|
return unmarshalJSONValueV2[JSONValue](v, dec)
|
|
}
|
|
|
|
func unmarshalJSONValue[T any](v *JSONValue, data []byte) error {
|
|
if string(data) == "null" {
|
|
*v = JSONValue{Type: JSONValueTypeNull}
|
|
} else if data[0] == '"' {
|
|
v.Type = JSONValueTypeString
|
|
return json.Unmarshal(data, &v.Value)
|
|
} else if data[0] == '[' {
|
|
var elements []T
|
|
if err := json.Unmarshal(data, &elements); err != nil {
|
|
return err
|
|
}
|
|
v.Type = JSONValueTypeArray
|
|
v.Value = elements
|
|
} else if data[0] == '{' {
|
|
var object collections.OrderedMap[string, T]
|
|
if err := json.Unmarshal(data, &object); err != nil {
|
|
return err
|
|
}
|
|
v.Type = JSONValueTypeObject
|
|
v.Value = &object
|
|
} else if string(data) == "true" {
|
|
v.Type = JSONValueTypeBoolean
|
|
v.Value = true
|
|
} else if string(data) == "false" {
|
|
v.Type = JSONValueTypeBoolean
|
|
v.Value = false
|
|
} else {
|
|
v.Type = JSONValueTypeNumber
|
|
return json.Unmarshal(data, &v.Value)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func unmarshalJSONValueV2[T any](v *JSONValue, dec *jsontext.Decoder) error {
|
|
switch dec.PeekKind() {
|
|
case 'n': // jsontext.Null.Kind()
|
|
if _, err := dec.ReadToken(); err != nil {
|
|
return err
|
|
}
|
|
v.Value = nil
|
|
v.Type = JSONValueTypeNull
|
|
return nil
|
|
case '"':
|
|
v.Type = JSONValueTypeString
|
|
if err := json.UnmarshalDecode(dec, &v.Value); err != nil {
|
|
return err
|
|
}
|
|
case '[':
|
|
if _, err := dec.ReadToken(); err != nil {
|
|
return err
|
|
}
|
|
var elements []T
|
|
for dec.PeekKind() != jsontext.EndArray.Kind() {
|
|
var element T
|
|
if err := json.UnmarshalDecode(dec, &element); err != nil {
|
|
return err
|
|
}
|
|
elements = append(elements, element)
|
|
}
|
|
if _, err := dec.ReadToken(); err != nil {
|
|
return err
|
|
}
|
|
v.Type = JSONValueTypeArray
|
|
v.Value = elements
|
|
case '{':
|
|
var object collections.OrderedMap[string, T]
|
|
if err := json.UnmarshalDecode(dec, &object); err != nil {
|
|
return err
|
|
}
|
|
v.Type = JSONValueTypeObject
|
|
v.Value = &object
|
|
case 't', 'f': // jsontext.True.Kind(), jsontext.False.Kind()
|
|
v.Type = JSONValueTypeBoolean
|
|
if err := json.UnmarshalDecode(dec, &v.Value); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
v.Type = JSONValueTypeNumber
|
|
if err := json.UnmarshalDecode(dec, &v.Value); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|