← Home

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!