Compare commits
No commits in common. "e0d73b537145d4ab0efb771b82f0c16fc99fc033" and "3252e0dde7feaa4fa8fb57f9c57f0909b850b271" have entirely different histories.
e0d73b5371
...
3252e0dde7
3 changed files with 7 additions and 93 deletions
22
README.md
22
README.md
|
@ -1,31 +1,11 @@
|
|||
# go-jsonschema
|
||||
|
||||
A [JSON schema] code generator for Go.
|
||||
|
||||
JSON schema draft 2020-12 is supported.
|
||||
A JSON schema code generator for Go.
|
||||
|
||||
## Usage
|
||||
|
||||
jsonschemagen -s <schema> -o <output>
|
||||
|
||||
One Go type per definition will be generated.
|
||||
|
||||
- `int64` is used for `"type": "integer"`.
|
||||
- `json.Number` is used for `"type": "number"`.
|
||||
- Go structs are generated for objects with `"additionalProperties": false`.
|
||||
- `json.RawMessage` is used when a value can have multiple types. Helpers are
|
||||
generated for `allOf`, `anyOf`, `oneOf`, `then`, `else` and `dependantSchemas`
|
||||
which are references.
|
||||
|
||||
## Contributing
|
||||
|
||||
Report bugs and send patches to the [mailing list]. Discuss in [#emersion] on
|
||||
Libera Chat.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
[JSON schema]: https://json-schema.org/
|
||||
[mailing list]: https://lists.sr.ht/~emersion/public-inbox
|
||||
[#emersion]: ircs://irc.libera.chat/#emersion
|
||||
|
|
|
@ -52,11 +52,8 @@ func resolveRef(def *jsonschema.Schema, root *jsonschema.Schema) *jsonschema.Sch
|
|||
}
|
||||
|
||||
func schemaType(schema *jsonschema.Schema) jsonschema.Type {
|
||||
switch {
|
||||
case len(schema.Type) == 1:
|
||||
return schema.Type[0]
|
||||
case len(schema.Type) > 0:
|
||||
return ""
|
||||
if schema.Type != "" {
|
||||
return schema.Type
|
||||
}
|
||||
|
||||
var v interface{}
|
||||
|
@ -128,40 +125,9 @@ func noAdditionalProps(schema *jsonschema.Schema) bool {
|
|||
return schema.AdditionalProperties != nil && schema.AdditionalProperties.IsFalse()
|
||||
}
|
||||
|
||||
// unwrapNullableSchema unwraps a schema in the form:
|
||||
//
|
||||
// {
|
||||
// "oneOf": {
|
||||
// { "type": "null" },
|
||||
// <sub-schema>
|
||||
// }
|
||||
// }
|
||||
func unwrapNullableSchema(schema *jsonschema.Schema) (*jsonschema.Schema, bool) {
|
||||
for _, choices := range [][]jsonschema.Schema{schema.AnyOf, schema.OneOf} {
|
||||
if len(choices) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
nullIndex := -1
|
||||
for i, choice := range choices {
|
||||
if len(choice.Type) == 1 && choice.Type[0] == jsonschema.TypeNull {
|
||||
nullIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if nullIndex < 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
otherIndex := (nullIndex + 1) % 2
|
||||
return &choices[otherIndex], true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func generateSchemaType(schema *jsonschema.Schema, root *jsonschema.Schema, required bool) jen.Code {
|
||||
if schema == nil {
|
||||
schema = &jsonschema.Schema{}
|
||||
return jen.Interface()
|
||||
}
|
||||
|
||||
refName := refName(schema.Ref)
|
||||
|
@ -174,10 +140,6 @@ func generateSchemaType(schema *jsonschema.Schema, root *jsonschema.Schema, requ
|
|||
return t
|
||||
}
|
||||
|
||||
if subschema, ok := unwrapNullableSchema(schema); ok {
|
||||
return jen.Op("*").Add(generateSchemaType(subschema, root, true))
|
||||
}
|
||||
|
||||
switch schemaType(schema) {
|
||||
case jsonschema.TypeNull:
|
||||
return jen.Struct()
|
||||
|
@ -186,7 +148,7 @@ func generateSchemaType(schema *jsonschema.Schema, root *jsonschema.Schema, requ
|
|||
case jsonschema.TypeArray:
|
||||
return jen.Index().Add(generateSchemaType(schema.Items, root, required))
|
||||
case jsonschema.TypeNumber:
|
||||
return jen.Qual("encoding/json", "Number")
|
||||
return jen.Float64()
|
||||
case jsonschema.TypeString:
|
||||
return jen.String()
|
||||
case jsonschema.TypeInteger:
|
||||
|
@ -227,15 +189,6 @@ func generateDef(schema *jsonschema.Schema, root *jsonschema.Schema, f *jen.File
|
|||
for _, child := range schema.OneOf {
|
||||
children = append(children, child)
|
||||
}
|
||||
if schema.Then != nil {
|
||||
children = append(children, *schema.Then)
|
||||
}
|
||||
if schema.Else != nil {
|
||||
children = append(children, *schema.Else)
|
||||
}
|
||||
for _, child := range schema.DependentSchemas {
|
||||
children = append(children, child)
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
refName := refName(child.Ref)
|
||||
|
|
23
schema.go
23
schema.go
|
@ -17,25 +17,6 @@ const (
|
|||
TypeInteger Type = "integer"
|
||||
)
|
||||
|
||||
type TypeSet []Type
|
||||
|
||||
func (ts *TypeSet) UnmarshalJSON(b []byte) error {
|
||||
if b[0] == '[' {
|
||||
type rawTypeSet TypeSet
|
||||
out := (*rawTypeSet)(ts)
|
||||
return json.Unmarshal(b, out)
|
||||
} else {
|
||||
var t Type
|
||||
err := json.Unmarshal(b, &t)
|
||||
if err != nil {
|
||||
*ts = nil
|
||||
} else {
|
||||
*ts = []Type{t}
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
type Schema struct {
|
||||
// Core
|
||||
Schema string `json:"$schema"`
|
||||
|
@ -70,7 +51,7 @@ type Schema struct {
|
|||
PropertyNames *Schema `json:"propertyNames"`
|
||||
|
||||
// Validation
|
||||
Type TypeSet `json:"type"`
|
||||
Type Type `json:"type"`
|
||||
Enum []interface{} `json:"enum"`
|
||||
Const interface{} `json:"const"`
|
||||
|
||||
|
@ -111,7 +92,7 @@ type Schema struct {
|
|||
|
||||
func (schema *Schema) UnmarshalJSON(b []byte) error {
|
||||
if bytes.Equal(b, []byte("true")) {
|
||||
*schema = Schema{}
|
||||
// Nothing to do
|
||||
} else if bytes.Equal(b, []byte("false")) {
|
||||
*schema = Schema{Not: []Schema{
|
||||
Schema{},
|
||||
|
|
Loading…
Reference in a new issue