jsonstruct is both a library and a command line tool to produce Go structs based on example JSON text. I just
refactored this pretty heavily, so there may still be bugs. It uses gofumpt to
format its output.
go install github.com/cneill/jsonstruct/cmd/jsonstruct@latestNAME:
jsonstruct - generate Go structs for JSON values
USAGE:
jsonstruct [global options] command [command options] [FILE]...
DESCRIPTION:
You can either pass in files as args or JSON in STDIN. Results are printed to STDOUT.
COMMANDS:
http run a web app to generate structs in the browser
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--name value, -n value override the default name derived from filename
--value-comments, -c add a comment to struct fields with the example value(s) (default: false)
--sort-fields, -s sort the fields in alphabetical order; default behavior is to mirror input (default: false)
--inline-structs, -i use inline structs instead of creating different types for each object (default: false)
--print-filenames, -f print the filename above the structs defined within (default: false)
--out-file FILE, -o FILE write the results to FILE
--debug, -d enable debug logs (default: false)
--help, -h show help
The http command allows you to run a webapp to generate these structs in the browser.
Input:
{
"currency": "value",
"amount": 4.267,
"map": {
"something": "nothing",
"this": true
},
"array": [
1,
2,
3,
4
],
"string_array": [
"string",
"string2",
"string3"
],
"CamelKey": "blah",
"blahBlahBlah": "blah",
"structs": [
{
"stuff": "stuff"
},
{
"stuff": "stuff2"
},
{
"stuff": "stuff3",
"differentStuff": "differentStuff"
}
],
"nested_numbers": [
[1, 2, 3],
[2, 3, 4],
[3, 4, 5]
],
"nothing": null
}Output:
typeStdin1struct {
Currencystring`json:"currency"`Amountfloat64`json:"amount"`Map*Map`json:"map"`Array []int64`json:"array"`StringArray []string`json:"string_array"`CamelKeystringBlahBlahBlahstring`json:"blahBlahBlah"`Structs []*Structs`json:"structs"`NestedNumbers [][]int64`json:"nested_numbers"`Nothing*json.RawMessage`json:"nothing"`
}
typeMapstruct {
Somethingstring`json:"something"`Thisbool`json:"this"`
}
typeStructsstruct {
Stuffstring`json:"stuff"`DifferentStuffstring`json:"differentStuff,omitempty"`
}Input:
[
{
"stuff": "stuff"
},
{
"stuff": "stuff2"
},
{
"stuff": "stuff3",
"differentStuff": "differentStuff"
},
{
"stuff": 1,
"differentStuff": "blah"
}
]Output:
typeStdin1struct {
Stuff*json.RawMessage`json:"stuff"`DifferentStuffstring`json:"differentStuff,omitempty"`
}Input:
{
"test_bool": true,
"test_int64": 1234,
"test_float64": 1234.0,
"test_string": "test",
"test_array_of_bool": [true, false, true],
"test_array_of_int64": [1, 2, 3, 4],
"test_array_of_float64": [1.0, 2.0, 3.0, 4.0],
"test_array_of_string": ["test1", "test2", "test3"],
"test_struct": {
"test_string": "test",
"test_array_of_string": ["test1", "test2", "test3"]
},
"test_array_of_struct": [
{
"test_string": "test1",
"test_optional_string": "test1"
},
{
"test_string": "test2",
"test_optional_string": "test2"
},
{
"test_string": "test3"
},
{
"test_string": "test4"
}
],
"test_garbage_array": [1, "1", 1.0],
"terrible-name.for_a.key": "test"
}Output:
typeStdin1struct {
TestBoolbool`json:"test_bool"`// Example: trueTestInt64int64`json:"test_int64"`// Example: 1234TestFloat64float64`json:"test_float64"`// Example: 1234.000TestStringstring`json:"test_string"`// Example: "test"TestArrayOfBool []bool`json:"test_array_of_bool"`// Example: [true, false, true]TestArrayOfInt64 []int64`json:"test_array_of_int64"`// Example: [1, 2, 3, 4]TestArrayOfFloat64 []float64`json:"test_array_of_float64"`// Example: [1.000, 2.000, 3.000, 4.000]TestArrayOfString []string`json:"test_array_of_string"`// Example: ["test1", "test2", "test3"]TestStruct*TestStruct`json:"test_struct"`TestArrayOfStruct []*TestArrayOfStruct`json:"test_array_of_struct"`TestGarbageArray []*json.RawMessage`json:"test_garbage_array"`TerribleNameForAKeystring`json:"terrible-name.for_a.key"`// Example: "test"
}
typeTestStructstruct {
TestStringstring`json:"test_string"`// Example: "test"TestArrayOfString []string`json:"test_array_of_string"`// Example: ["test1", "test2", "test3"]
}
typeTestArrayOfStructstruct {
TestStringstring`json:"test_string"`// Example: "test1"TestOptionalStringstring`json:"test_optional_string,omitempty"`// Example: "test1"
}Input:
{
"test_struct": {
"test_string": "test",
"test_array_of_string": ["test1", "test2", "test3"]
},
"test_array_of_struct": [
{
"test_string": "test1",
"test_optional_string": "test1"
},
{
"test_string": "test2",
"test_optional_string": "test2"
},
{
"test_string": "test3"
},
{
"test_string": "test4"
}
]
}Output:
typeStdin1struct {
TestStructstruct {
TestStringstring`json:"test_string"`TestArrayOfString []string`json:"test_array_of_string"`
} `json:"test_struct"`TestArrayOfStruct []struct {
TestStringstring`json:"test_string"`TestOptionalStringstring`json:"test_optional_string,omitempty"`
} `json:"test_array_of_struct"`
}- When an array of JSON objects is detected, any keys that are provided in some objects but not others
will get the
,omitemptyflag - When the same field is detected in multiple objects in a JSON array with different value types, the
Go type will be
*json.RawMessage, which will contain the raw bytes of the field to allow for different types - Defaults to a
*json.RawMessagetype when:- JSON
nullis provided - There are multiple types in e.g. an array
- There is an empty array
- JSON
- Can take input from either files passed in as CLI args or STDIN. Can take a stream of objects / arrays of objects.
- De-duplicate structs that are created more than once by multiple instances in the example JSON file
- Handle plural names for slice types
