blob: 3187c455ec10260b501a5b75a3b076daf61f6ba6 [file] [log] [blame]
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package jsonschema
import (
"fmt"
"gopkg.in/yaml.v2"
)
const indentation = " "
func renderMap(info interface{}, indent string) (result string) {
result = "{\n"
innerIndent := indent + indentation
switch pairs := info.(type) {
case yaml.MapSlice:
for i, pair := range pairs {
// first print the key
result += fmt.Sprintf("%s\"%+v\": ", innerIndent, pair.Key)
// then the value
switch value := pair.Value.(type) {
case string:
result += "\"" + value + "\""
case bool:
if value {
result += "true"
} else {
result += "false"
}
case []interface{}:
result += renderArray(value, innerIndent)
case yaml.MapSlice:
result += renderMap(value, innerIndent)
case int:
result += fmt.Sprintf("%d", value)
case int64:
result += fmt.Sprintf("%d", value)
case []string:
result += renderStringArray(value, innerIndent)
default:
result += fmt.Sprintf("???MapItem(Key:%+v, Value:%T)", value, value)
}
if i < len(pairs)-1 {
result += ","
}
result += "\n"
}
default:
// t is some other type that we didn't name.
}
result += indent + "}"
return result
}
func renderArray(array []interface{}, indent string) (result string) {
result = "[\n"
innerIndent := indent + indentation
for i, item := range array {
switch item := item.(type) {
case string:
result += innerIndent + "\"" + item + "\""
case bool:
if item {
result += innerIndent + "true"
} else {
result += innerIndent + "false"
}
case yaml.MapSlice:
result += innerIndent + renderMap(item, innerIndent) + ""
default:
result += innerIndent + fmt.Sprintf("???ArrayItem(%+v)", item)
}
if i < len(array)-1 {
result += ","
}
result += "\n"
}
result += indent + "]"
return result
}
func renderStringArray(array []string, indent string) (result string) {
result = "[\n"
innerIndent := indent + indentation
for i, item := range array {
result += innerIndent + "\"" + item + "\""
if i < len(array)-1 {
result += ","
}
result += "\n"
}
result += indent + "]"
return result
}
func Render(info yaml.MapSlice) string {
return renderMap(info, "") + "\n"
}
func (object *SchemaNumber) jsonValue() interface{} {
if object.Integer != nil {
return object.Integer
} else if object.Float != nil {
return object.Float
} else {
return nil
}
}
func (object *SchemaOrBoolean) jsonValue() interface{} {
if object.Schema != nil {
return object.Schema.jsonValue()
} else if object.Boolean != nil {
return *object.Boolean
} else {
return nil
}
}
func (object *StringOrStringArray) jsonValue() interface{} {
if object.String != nil {
return *object.String
} else if object.StringArray != nil {
array := make([]interface{}, 0)
for _, item := range *(object.StringArray) {
array = append(array, item)
}
return array
} else {
return nil
}
}
func (object *SchemaOrStringArray) jsonValue() interface{} {
if object.Schema != nil {
return object.Schema.jsonValue()
} else if object.StringArray != nil {
array := make([]interface{}, 0)
for _, item := range *(object.StringArray) {
array = append(array, item)
}
return array
} else {
return nil
}
}
func (object *SchemaOrSchemaArray) jsonValue() interface{} {
if object.Schema != nil {
return object.Schema.jsonValue()
} else if object.SchemaArray != nil {
array := make([]interface{}, 0)
for _, item := range *(object.SchemaArray) {
array = append(array, item.jsonValue())
}
return array
} else {
return nil
}
}
func (object *SchemaEnumValue) jsonValue() interface{} {
if object.String != nil {
return *object.String
} else if object.Bool != nil {
return *object.Bool
} else {
return nil
}
}
func namedSchemaArrayValue(array *[]*NamedSchema) interface{} {
m2 := yaml.MapSlice{}
for _, pair := range *(array) {
var item2 yaml.MapItem
item2.Key = pair.Name
item2.Value = pair.Value.jsonValue()
m2 = append(m2, item2)
}
return m2
}
func namedSchemaOrStringArrayValue(array *[]*NamedSchemaOrStringArray) interface{} {
m2 := yaml.MapSlice{}
for _, pair := range *(array) {
var item2 yaml.MapItem
item2.Key = pair.Name
item2.Value = pair.Value.jsonValue()
m2 = append(m2, item2)
}
return m2
}
func schemaEnumArrayValue(array *[]SchemaEnumValue) []interface{} {
a := make([]interface{}, 0)
for _, item := range *array {
a = append(a, item.jsonValue())
}
return a
}
func schemaArrayValue(array *[]*Schema) []interface{} {
a := make([]interface{}, 0)
for _, item := range *array {
a = append(a, item.jsonValue())
}
return a
}
func (schema *Schema) jsonValue() yaml.MapSlice {
m := yaml.MapSlice{}
if schema.Title != nil {
m = append(m, yaml.MapItem{Key: "title", Value: *schema.Title})
}
if schema.ID != nil {
m = append(m, yaml.MapItem{Key: "id", Value: *schema.ID})
}
if schema.Schema != nil {
m = append(m, yaml.MapItem{Key: "$schema", Value: *schema.Schema})
}
if schema.Type != nil {
m = append(m, yaml.MapItem{Key: "type", Value: schema.Type.jsonValue()})
}
if schema.Items != nil {
m = append(m, yaml.MapItem{Key: "items", Value: schema.Items.jsonValue()})
}
if schema.Description != nil {
m = append(m, yaml.MapItem{Key: "description", Value: *schema.Description})
}
if schema.Required != nil {
m = append(m, yaml.MapItem{Key: "required", Value: *schema.Required})
}
if schema.AdditionalProperties != nil {
m = append(m, yaml.MapItem{Key: "additionalProperties", Value: schema.AdditionalProperties.jsonValue()})
}
if schema.PatternProperties != nil {
m = append(m, yaml.MapItem{Key: "patternProperties", Value: namedSchemaArrayValue(schema.PatternProperties)})
}
if schema.Properties != nil {
m = append(m, yaml.MapItem{Key: "properties", Value: namedSchemaArrayValue(schema.Properties)})
}
if schema.Dependencies != nil {
m = append(m, yaml.MapItem{Key: "dependencies", Value: namedSchemaOrStringArrayValue(schema.Dependencies)})
}
if schema.Ref != nil {
m = append(m, yaml.MapItem{Key: "$ref", Value: *schema.Ref})
}
if schema.MultipleOf != nil {
m = append(m, yaml.MapItem{Key: "multipleOf", Value: schema.MultipleOf.jsonValue()})
}
if schema.Maximum != nil {
m = append(m, yaml.MapItem{Key: "maximum", Value: schema.Maximum.jsonValue()})
}
if schema.ExclusiveMaximum != nil {
m = append(m, yaml.MapItem{Key: "exclusiveMaximum", Value: schema.ExclusiveMaximum})
}
if schema.Minimum != nil {
m = append(m, yaml.MapItem{Key: "minimum", Value: schema.Minimum.jsonValue()})
}
if schema.ExclusiveMinimum != nil {
m = append(m, yaml.MapItem{Key: "exclusiveMinimum", Value: schema.ExclusiveMinimum})
}
if schema.MaxLength != nil {
m = append(m, yaml.MapItem{Key: "maxLength", Value: *schema.MaxLength})
}
if schema.MinLength != nil {
m = append(m, yaml.MapItem{Key: "minLength", Value: *schema.MinLength})
}
if schema.Pattern != nil {
m = append(m, yaml.MapItem{Key: "pattern", Value: *schema.Pattern})
}
if schema.AdditionalItems != nil {
m = append(m, yaml.MapItem{Key: "additionalItems", Value: schema.AdditionalItems.jsonValue()})
}
if schema.MaxItems != nil {
m = append(m, yaml.MapItem{Key: "maxItems", Value: *schema.MaxItems})
}
if schema.MinItems != nil {
m = append(m, yaml.MapItem{Key: "minItems", Value: *schema.MinItems})
}
if schema.UniqueItems != nil {
m = append(m, yaml.MapItem{Key: "uniqueItems", Value: *schema.UniqueItems})
}
if schema.MaxProperties != nil {
m = append(m, yaml.MapItem{Key: "maxProperties", Value: *schema.MaxProperties})
}
if schema.MinProperties != nil {
m = append(m, yaml.MapItem{Key: "minProperties", Value: *schema.MinProperties})
}
if schema.Enumeration != nil {
m = append(m, yaml.MapItem{Key: "enum", Value: schemaEnumArrayValue(schema.Enumeration)})
}
if schema.AllOf != nil {
m = append(m, yaml.MapItem{Key: "allOf", Value: schemaArrayValue(schema.AllOf)})
}
if schema.AnyOf != nil {
m = append(m, yaml.MapItem{Key: "anyOf", Value: schemaArrayValue(schema.AnyOf)})
}
if schema.OneOf != nil {
m = append(m, yaml.MapItem{Key: "oneOf", Value: schemaArrayValue(schema.OneOf)})
}
if schema.Not != nil {
m = append(m, yaml.MapItem{Key: "not", Value: schema.Not.jsonValue()})
}
if schema.Definitions != nil {
m = append(m, yaml.MapItem{Key: "definitions", Value: namedSchemaArrayValue(schema.Definitions)})
}
if schema.Default != nil {
m = append(m, yaml.MapItem{Key: "default", Value: *schema.Default})
}
if schema.Format != nil {
m = append(m, yaml.MapItem{Key: "format", Value: *schema.Format})
}
return m
}
// JSONString returns a json representation of a schema.
func (schema *Schema) JSONString() string {
info := schema.jsonValue()
return Render(info)
}