2025-10-15 10:12:44 +03:00

76 lines
1.5 KiB
Go

package packagejson
import (
"reflect"
"github.com/go-json-experiment/json"
)
type Expected[T any] struct {
actualJSONType string
Null bool
Valid bool
Value T
}
func (e *Expected[T]) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
*e = Expected[T]{Null: true, actualJSONType: "null"}
return nil
}
if json.Unmarshal(data, &e.Value) == nil {
e.Valid = true
}
switch data[0] {
case '"':
e.actualJSONType = "string"
case 't', 'f':
e.actualJSONType = "boolean"
case '[':
e.actualJSONType = "array"
case '{':
e.actualJSONType = "object"
default:
e.actualJSONType = "number"
}
return nil
}
func (e *Expected[T]) IsPresent() bool {
return e.actualJSONType != ""
}
func (e *Expected[T]) GetValue() (value T, ok bool) {
return e.Value, e.Valid
}
func (e *Expected[T]) IsValid() bool {
return e.Valid
}
func (e *Expected[T]) ExpectedJSONType() string {
switch reflect.TypeFor[T]().Kind() {
case reflect.String:
return "string"
case reflect.Bool:
return "boolean"
case reflect.Slice, reflect.Array:
return "array"
case reflect.Map:
return "object"
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return "number"
default:
return "unknown"
}
}
func (e *Expected[T]) ActualJSONType() string {
return e.actualJSONType
}
func ExpectedOf[T any](value T) Expected[T] {
return Expected[T]{Value: value, Valid: true, actualJSONType: (*Expected[T])(nil).ExpectedJSONType()}
}