JSON Schema to Go Struct Generator Roundup
I had some complex JSON to deserialize into Go structs and a matching JSON schema file. The JSON schema is likely to change a lot over the next few weeks, so I wondered “Is there was a way to create the Go structs automatically based on the JSON schema?”
I searched github.com and found a bunch of packages in various states, so I put together a cut-down version of my app’s schema and tried it out.
Test Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"address": {
"id": "address",
"type": "object",
"description": "Address",
"properties": {
"houseName": {
"type": "string",
"description": "House Name",
"maxLength": 30
},
"houseNumber": {
"type": "string",
"description": "House Number",
"maxLength": 4
},
"flatNumber": {
"type": "string",
"description": "Flat",
"maxLength": 15
},
"street": {
"type": "string",
"description": "Address 1",
"maxLength": 40
},
"district": {
"type": "string",
"description": "Address 2",
"maxLength": 30
},
"town": {
"type": "string",
"description": "City",
"maxLength": 20
},
"county": {
"type": "string",
"description": "County",
"maxLength": 20
},
"postcode": {
"type": "string",
"description": "Postcode",
"maxLength": 8
}
}
},
"status": {
"type": "object",
"properties": {
"favouriteCat": {
"enum": [
"A",
"B",
"C",
"D",
"E",
"F"
],
"type": "string",
"description": "The favourite cat.",
"maxLength": 1
}
}
}
},
"properties": {
"name": {
"type": "string"
},
"address": {
"$ref": "#/definitions/address"
},
"status": {
"$ref": "#/definitions/status"
}
}
}
https://github.com/interagent/schematic
Failed to work out of the box at all on my test schema. Issue raised: [0]
./schematic ~/goprojects/src/github.com/a-h/schemagenerators/exampleschema.json
schematic: 12:5: expected 'IDENT', found 'import'
https://github.com/idubinskiy/schematyper
Produced some workable-ish Go code. I was expecting the type “Example” to have properties for name, status and address, but it didn’t. Either way there are no unit tests so if it does work, it’s partly by luck.
package main
// generated by "./schematyper /Users/adrian/goprojects/src/github.com/a-h/schemagenerators/exampleschema.json" -- DO NOT EDIT
// Address
type address struct {
County string `json:"county,omitempty"`
District string `json:"district,omitempty"`
FlatNumber string `json:"flatNumber,omitempty"`
HouseName string `json:"houseName,omitempty"`
HouseNumber string `json:"houseNumber,omitempty"`
Postcode string `json:"postcode,omitempty"`
Street string `json:"street,omitempty"`
Town string `json:"town,omitempty"`
}
type exampleschema interface{}
type status struct {
FavouriteCat string `json:"favouriteCat,omitempty"`
}
https://github.com/x-formation/schemagen
Looks OK, but relies on some more packages from the author to do with bin-data which I don’t think should be required. Maybe this is for personal use?
https://github.com/snikch/schematype
OK, it’s got a beta warning and no unit tests. Let’s do this.
Sadly, it doesn’t compile right now, left an issue, got a nice message from the author.
https://github.com/schorsch/go-json-schema-tools
Needs some stuff that runs from [1] couldn’t be bothered installing the Mercurial tools.
Next
OK, so after this, I got bored and decided to fix the bug in schematic because it has unit tests. The problem was actually with go format on the code that it produces:
https://github.com/interagent/schematic/pull/37
Once I’d fixed that, I got this code out of it, but it still lacked expected properties for the example type - name, address and status.
// Stuff related to making a HTTP call.
// Address
type Address struct {
County string `json:"county" url:"county,key"` // County
District string `json:"district" url:"district,key"` // Address 2
FlatNumber string `json:"flatNumber" url:"flatNumber,key"` // Flat
HouseName string `json:"houseName" url:"houseName,key"` // House Name
HouseNumber string `json:"houseNumber" url:"houseNumber,key"` // House Number
Postcode string `json:"postcode" url:"postcode,key"` // Postcode
Street string `json:"street" url:"street,key"` // Address 1
Town string `json:"town" url:"town,key"` // City
}
type Status struct {
Favouritecat string `json:"favouritecat" url:"favouritecat,key"` // The favourite cat.
}
Argh - I’m writing my own
So, I decided to write something that does what I need over at [2]
While I haven’t tested all of the JSON schema features (just the ones I need), it’s reasonably well unit tested and produces the output I was looking for:
package main
type Address struct {
County string `json:"county,omitempty"`
District string `json:"district,omitempty"`
FlatNumber string `json:"flatNumber,omitempty"`
HouseName string `json:"houseName,omitempty"`
HouseNumber string `json:"houseNumber,omitempty"`
Postcode string `json:"postcode,omitempty"`
Street string `json:"street,omitempty"`
Town string `json:"town,omitempty"`
}
type Example struct {
Address *Address `json:"address,omitempty"`
Name string `json:"name,omitempty"`
Status *Status `json:"status,omitempty"`
}
type Status struct {
Favouritecat string `json:"favouritecat,omitempty"`
}
I’ll be using it to work on a system over the next few weeks, so it’s likely to evolve. Ping me if you find it useful!