Skip to content

ctx42/jsontype

Repository files navigation

Go Report Card GoDoc Tests

jsontype is a small Go module that preserves Go types when marshaling values to JSON. It embeds type information directly into the JSON alongside the value.

This is useful in scenarios where you marshal and unmarshal JSON to composite types, such as map[string]any. It ensures that Go types are preserved during a round-trip.

Installation

Install using go get:

go get github.com/ctx42/jsontype

Example

Create a Value instance encapsulating the value and its type.

jType := jsontype.New(uint(42))
data, _ := json.Marshal(jType)

fmt.Println(string(data))
// Output:
// {"type":"uint","value":42}

Later when unmarshalling the library is looking at the type field, finds the matching converter in the package-level registry and converts the value.

data := []byte(`{"type": "uint", "value": 42}`)

gType := &jsontype.Value{}
_ = json.Unmarshal(data, gType)

fmt.Printf("%[1]v (%[1]T)\n", gType.GoValue())
// Output:
// 42 (uint)

Type Registry

The package-level registry provides converters for the following types:

  • int
  • int8
  • int16
  • int32
  • int64
  • uint
  • uint8
  • uint16
  • uint32
  • uint64
  • float32
  • float64
  • byte
  • rune
  • string
  • bool
  • time.Duration
  • time.Time
  • nil

Custom Converters

You may register a custom converter for your custom type.

// Custom converter for a type named "seconds" representing duration in seconds.
cnv := func(value float64) (time.Duration, error) {
    return time.Duration(value) * time.Second, nil
}

// Register converter.
jsontype.Register("seconds", convert.ToAnyAny(cnv))

// Custom type named "seconds" representing duration in seconds.
data := []byte(`{"type": "seconds", "value": 42}`)

gType := &jsontype.Value{}
err := json.Unmarshal(data, gType)

_ = err // Check error.

fmt.Printf("unmarshalled: %[1]v (%[1]T)\n", gType.GoValue())
// Output:
// unmarshalled: 42s (time.Duration)

The registered converter must return an error when conversion of a value from a JSON type to Go type would result in loss of precision, overflow, underflow or conversion is simply impossible. The same way how the github.com/ctx42/convert converter functions work.

About

Go module that preserves Go type information during JSON marshaling.

Topics

Resources

License

Stars

Watchers

Forks

Languages