https://github.com/byrnedo/pjson
Helps to easily JSON marshal / unmarshal tagged unions in go
https://github.com/byrnedo/pjson
discriminated-unions discriminator generics go json polymorphic-deserialization tagged-unions
Last synced: 16 days ago
JSON representation
Helps to easily JSON marshal / unmarshal tagged unions in go
- Host: GitHub
- URL: https://github.com/byrnedo/pjson
- Owner: byrnedo
- License: mit
- Created: 2022-07-21T14:57:31.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2023-04-11T11:27:24.000Z (about 2 years ago)
- Last Synced: 2025-04-09T20:15:35.147Z (16 days ago)
- Topics: discriminated-unions, discriminator, generics, go, json, polymorphic-deserialization, tagged-unions
- Language: Go
- Homepage:
- Size: 43.9 KB
- Stars: 20
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# pjson
[](https://github.com/byrnedo/pjson/blob/master/LICENSE.txt)
[](https://pkg.go.dev/github.com/byrnedo/pjson)
[](https://raw.githack.com/wiki/byrnedo/pjson/coverage.html)
[](https://goreportcard.com/report/github.com/byrnedo/pjson)Help to easily JSON marshal / unmarshal tagged unions in go
A tagged union / discriminating type is, for instance with the following JSON:
```json
[
{
"type": "a",
"a_name": "AName",
"a_foo": "FOO"
},
{
"type": "b",
"b_name": "BName",
"b_goo": "GOO"
}
]
```The `type` field denotes which type the object is. So many object share a common discriminating field.
In some languages this is supported, but not in go.**Pjson** gives us a helper `pjson.Tagged` type to create these pseudo tagged unions that can be automatically
serialized and deserialized to and from JSON.## Usage
```go
package readmeimport (
"encoding/json"
"fmt"
"reflect""github.com/byrnedo/pjson"
)type Foo struct {
A string `json:"a"`
}// set it's tag value
func (a Foo) Variant() string {
return "foo"
}type Bar struct {
B string `json:"b"`
}func (b Bar) Variant() string {
return "bar"
}// specify the union
type FooBarUnion struct{}func (u FooBarUnion) Field() string { return "type" }
func (u FooBarUnion) Variants() []pjson.Variant {
return []pjson.Variant{
Foo{}, Bar{},
}
}func ExampleReadme() {
// now that we have our types we can use Tagged
o := pjson.Tagged[FooBarUnion]{}bytes := []byte(`{"type": "foo", "a": "AAAA"}`)
err := json.Unmarshal(bytes, &o)
if err != nil {
panic(err)
}fmt.Println(reflect.TypeOf(o.Value), o.Value)
bytes, _ = json.Marshal(o)
fmt.Println(string(bytes))// Output: *pjson_test.Foo &{AAAA}
// {"a":"AAAA","type":"foo"}
}
```## Benchmarks
Macbook Pro M1 2022
```
Benchmark/unmarshal_with_pjson
Benchmark/unmarshal_with_pjson-10 867177 1356 ns/op
Benchmark/unmarshal_without_pjson
Benchmark/unmarshal_without_pjson-10 1793629 670.6 ns/op
Benchmark/marshal_with_pjson
Benchmark/marshal_with_pjson-10 2415705 488.7 ns/op
Benchmark/marshal_without_pjson
Benchmark/marshal_without_pjson-10 10956252 109.8 ns/op
```