diff --git a/reflect.go b/reflect.go index dd52529..034501d 100644 --- a/reflect.go +++ b/reflect.go @@ -277,7 +277,7 @@ func (r *Reflector) reflectTypeToSchemaWithID(defs Definitions, t reflect.Type) func (r *Reflector) reflectTypeToSchema(definitions Definitions, t reflect.Type) (res *Schema) { defer func() { if r.NullableFromType && isNullable(t.Kind()) { - res.makeNullable() + res.MakeNullable() } }() @@ -489,7 +489,7 @@ func (r *Reflector) reflectStructFields(st *Schema, definitions Definitions, t r if t.Kind() == reflect.Pointer { r.reflectStructFields(st, definitions, t.Elem()) if r.NullableFromType { - st.makeNullable() + st.MakeNullable() } return } @@ -534,8 +534,8 @@ func (r *Reflector) reflectStructFields(st *Schema, definitions Definitions, t r } unwrapped := property - if r.NullableFromType && unwrapped.isNullable() { - unwrapped = unwrapped.unwrapNullable() + if r.NullableFromType { + unwrapped = unwrapped.UnwrapNullable() } unwrapped.structKeywordsFromTags(f, st, name) if unwrapped.Description == "" { @@ -546,7 +546,7 @@ func (r *Reflector) reflectStructFields(st *Schema, definitions Definitions, t r } if nullable && !r.NullableFromType { // we already set the nullability if r.NullableFromType is set - property.makeNullable() + property.MakeNullable() } st.Properties.Set(name, property) @@ -627,25 +627,6 @@ func (r *Reflector) lookupID(t reflect.Type) ID { return EmptyID } -func (t *Schema) makeNullable() { - sc := *t - *t = Schema{OneOf: []*Schema{&sc, {Type: "null"}}} -} - -func (t *Schema) isNullable() bool { - return t.unwrapNullable() != nil -} - -func (t *Schema) unwrapNullable() *Schema { - if t.Type != "" { - return nil - } - if len(t.OneOf) != 2 || t.OneOf[1].Type != "null" { - return nil - } - return t.OneOf[0] -} - func (t *Schema) structKeywordsFromTags(f reflect.StructField, parent *Schema, propertyName string) { t.Description = f.Tag.Get("jsonschema_description") diff --git a/schema.go b/schema.go index 2d914b8..598dab2 100644 --- a/schema.go +++ b/schema.go @@ -88,6 +88,28 @@ var ( FalseSchema = &Schema{boolean: &[]bool{false}[0]} ) +// MakeNullable will replace the schema that either matches the schema or `null` value: +// The resulting schema is wrapped via `oneOf` feature. +// +// {"oneOf":[s,{"type":"null"}]} +func (t *Schema) MakeNullable() { + sc := *t + *t = Schema{OneOf: []*Schema{&sc, {Type: "null"}}} +} + +// IsNullable will test if the Schema is nullable in terms of MakeNullable +func (t *Schema) IsNullable() bool { + return len(t.OneOf) == 2 && t.OneOf[1].Type == "null" +} + +// UnwrapNullable will return the non-nullable schema part if the schema is nullable. +func (t *Schema) UnwrapNullable() *Schema { + if t.IsNullable() { + return t.OneOf[0] + } + return t +} + // Definitions hold schema definitions. // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.26 // RFC draft-wright-json-schema-validation-00, section 5.26