a-h / generate

Generates Go (golang) Structs from JSON schema.
MIT License
444 stars 137 forks source link

json: cannot unmarshal array into Go value of type string #12

Closed andygrunwald closed 6 years ago

andygrunwald commented 7 years ago

If you try to compile this example:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "name": "Repository Configuration",
    "type": "object",
    "additionalProperties": false,
    "required": [ "name" ],
    "properties": {
        "name": {
            "type": "string",
            "description": "Repository name."
        },
        "repositories": {
            "type": ["object", "array"],
            "description": "A set of additional repositories where packages can be found.",
            "additionalProperties": true
        }
    }
}

via

$ go run main.go -i min.json
Failed to parse the input JSON schema with error  json: cannot unmarshal array into Go value of type string

If you change "type": ["object", "array"] to "type": "object", it works and produces

package main

type Root struct {
  Name string `json:"name,omitempty"`
  Repositories * `json:"repositories,omitempty"`
}

To be honest: This is tricky. I don`t know how to react or solve this one. Maybe you got an idea and we can discuss it?

andygrunwald commented 7 years ago

Maybe those types need to be flagged as interface{}?

a-h commented 7 years ago

Yeah, it's difficult to know how to handle a field that can be one of two things, e.g. an object or an array of objects.

Your idea of using interface{} would allow the schema to be handled, even though you'd end up having to use type assertions to figure out what it was:

[https://play.golang.org/p/89O8MrWnm_]

Do you think it should generate helper functions to access the values appropriately, or just dump out interface{} in the generated schema?

andygrunwald commented 7 years ago

@a-h Your snipped can't be found anymore. Anyway.

Do you think it should generate helper functions to access the values appropriately, or just dump out interface{} in the generated schema?

Both ideas are good. An alternative idea would be to throw out a log message like field X can't be parsed, because of reason Y. IMO generate is often used as a one time tool and after this the generated code will be modified. All suggested options are fine. I think in the end it would be your choice in relation to the time you have available for development.

  1. Add this limitation to the README
  2. A message "field x can't be parsed" would be cool to inform the user
  3. Generating an interface{} would be good
  4. Generating helper methods are king

This is my rate scala where 0. is less effort and 3. the most.

a-h commented 6 years ago

Hey @andygrunwald, got a chance to look at this and created https://github.com/a-h/generate/pull/33

For cases where there are multiple possible types, e.g. string or number, it generates using interface{}, clients can unpack the values using type assertions, so it's item 2 on your list.

Look good to you?