polyjson

package module
v0.0.0-...-62fbeaa Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2025 License: MIT Imports: 6 Imported by: 0

README

Go PolyJSON

Go Code generator of JSON marshalers/unmarshalers for polymorphic data structures.

Usage

go install codeberg.org/polyfloyd/go-polyjson/cmd/polyjson@latest

The program targets a single package and generates marshalers for one or more polymorphic types along with unmarshalers for structures that use such polymorphic types in fields.

The recommended usage is to define an interface denoting the polymorphic types with at least a method that:

  • Takes no arguments
  • Returns nothing
  • Is private (starts with a lowercase letter)

The program will automatically discover associated variants that implement this interface.

package shapes

type Shape interface {
	iShape()
}

func (Triangle) iShape() {}
func (Square) iShape()   {}

type Square struct {
	TopLeft       [2]int
	Width, Height int
}

type Triangle struct {
	P0 [2]int
	P1 [2]int
	P2 [2]int
}

Invoke the generator by specifying the name of the interface with -type:

polyjson -type Shape -package ./shapes

This will place a polyjsongen.go file in the package specified containing the (un)marshalers.

Now, you can encode and decode your data like this:

inputShape := Square{TopLeft: [2]int{1, 2}, Width: 4, Height: 4}

b, err := json.Marshal(inputShape)
fmt.Printf("%s\n", b) // {"kind": "Square", "TopLeft": [1, 2], "Width": 4, "Height": 4}

decodedShape, err := UnmarshalShapeJSON(b)
fmt.Printf("%T\n", decodedShape) // Square

Reference

Discriminant

Each struct that is encoded to JSON that is a variant of a polymorphic type gains an additional field that holds the name of the type. It is placed in between the other fields of the struct. The default name of this field is kind and it can be altered by setting the -discriminant flag.

Specifying types

The -type argument accepts a polymorphic type specification in the following forms:

  • -type Shape Interface only
  • -type Shape:Triangle,Square Interface with explicitly named variants
  • -type Shape:Triangle=triangle_shape,Square=square_shape Interface with explicitly named variants and their JSON counterparts
Usage in Go

To encode a struct, just use json.Marshal like you normally would.

To decode a polymorphic type, use the generated Unmarshal<type>JSON, e.g. UnmarshalShapeJSON. This will probe the JSON object for the variant kind and unmarshal into the associated struct.

Interoperability with Rust and Serde

PolyJSON was initially made for exchanging data between Go and Rust services. Rust in combination with serde_json can understand the format generated by this tool like so:

#[derive(Serialize, Deserialize)]
#[serde(tag = "kind")]
pub enum Shape {
	Square {
		top_left: [i32; 2],
		width: i32,
		height: i32,
	},
	Triangle {
		p0: [i32; 2],
		p1: [i32; 2],
		p2: [i32; 2],
	},
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func WriteMarshalerFile

func WriteMarshalerFile(filename, goPackage string, types []Type, structs []Struct) error

Types

type Struct

type Struct struct {
	Name              string
	PolymorphicFields []StructField
}

func PolymorphicStructFields

func PolymorphicStructFields(files []*ast.File, polymorphicTypes []string) ([]Struct, error)

type StructField

type StructField struct {
	Name     string // Name of the field in the struct.
	JSONName string // Name of the field as encoded in JSON.
	Type     string // Name of the polymorphic type.
	Kind     string // How the unmarshaling logic should behave. "Scalar" | "Slice" | "Map"
}

type Type

type Type struct {
	Name         string
	Variants     []TypeVariant
	Discriminant string
}

func TypeFromInterface

func TypeFromInterface(files []*ast.File, args TypeFromInterfaceArgs) (*Type, error)

type TypeFromInterfaceArgs

type TypeFromInterfaceArgs struct {
	Interface    string
	Discriminant string
	VariantRemap map[string]string
}

type TypeVariant

type TypeVariant struct {
	Name     string
	JSONName string
}

Directories

Path Synopsis
cmd
polyjson command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL