...

Source file src/github.com/google/gnostic-models/jsonschema/writer.go

Documentation: github.com/google/gnostic-models/jsonschema

     1  // Copyright 2017 Google LLC. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package jsonschema
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"gopkg.in/yaml.v3"
    21  )
    22  
    23  const indentation = "  "
    24  
    25  func renderMappingNode(node *yaml.Node, indent string) (result string) {
    26  	result = "{\n"
    27  	innerIndent := indent + indentation
    28  	for i := 0; i < len(node.Content); i += 2 {
    29  		// first print the key
    30  		key := node.Content[i].Value
    31  		result += fmt.Sprintf("%s\"%+v\": ", innerIndent, key)
    32  		// then the value
    33  		value := node.Content[i+1]
    34  		switch value.Kind {
    35  		case yaml.ScalarNode:
    36  			result += "\"" + value.Value + "\""
    37  		case yaml.MappingNode:
    38  			result += renderMappingNode(value, innerIndent)
    39  		case yaml.SequenceNode:
    40  			result += renderSequenceNode(value, innerIndent)
    41  		default:
    42  			result += fmt.Sprintf("???MapItem(Key:%+v, Value:%T)", value, value)
    43  		}
    44  		if i < len(node.Content)-2 {
    45  			result += ","
    46  		}
    47  		result += "\n"
    48  	}
    49  
    50  	result += indent + "}"
    51  	return result
    52  }
    53  
    54  func renderSequenceNode(node *yaml.Node, indent string) (result string) {
    55  	result = "[\n"
    56  	innerIndent := indent + indentation
    57  	for i := 0; i < len(node.Content); i++ {
    58  		item := node.Content[i]
    59  		switch item.Kind {
    60  		case yaml.ScalarNode:
    61  			result += innerIndent + "\"" + item.Value + "\""
    62  		case yaml.MappingNode:
    63  			result += innerIndent + renderMappingNode(item, innerIndent) + ""
    64  		default:
    65  			result += innerIndent + fmt.Sprintf("???ArrayItem(%+v)", item)
    66  		}
    67  		if i < len(node.Content)-1 {
    68  			result += ","
    69  		}
    70  		result += "\n"
    71  	}
    72  	result += indent + "]"
    73  	return result
    74  }
    75  
    76  func renderStringArray(array []string, indent string) (result string) {
    77  	result = "[\n"
    78  	innerIndent := indent + indentation
    79  	for i, item := range array {
    80  		result += innerIndent + "\"" + item + "\""
    81  		if i < len(array)-1 {
    82  			result += ","
    83  		}
    84  		result += "\n"
    85  	}
    86  	result += indent + "]"
    87  	return result
    88  }
    89  
    90  // Render renders a yaml.Node as JSON
    91  func Render(node *yaml.Node) string {
    92  	if node.Kind == yaml.DocumentNode {
    93  		if len(node.Content) == 1 {
    94  			return Render(node.Content[0])
    95  		}
    96  	} else if node.Kind == yaml.MappingNode {
    97  		return renderMappingNode(node, "") + "\n"
    98  	} else if node.Kind == yaml.SequenceNode {
    99  		return renderSequenceNode(node, "") + "\n"
   100  	}
   101  	return ""
   102  }
   103  
   104  func (object *SchemaNumber) nodeValue() *yaml.Node {
   105  	if object.Integer != nil {
   106  		return nodeForInt64(*object.Integer)
   107  	} else if object.Float != nil {
   108  		return nodeForFloat64(*object.Float)
   109  	} else {
   110  		return nil
   111  	}
   112  }
   113  
   114  func (object *SchemaOrBoolean) nodeValue() *yaml.Node {
   115  	if object.Schema != nil {
   116  		return object.Schema.nodeValue()
   117  	} else if object.Boolean != nil {
   118  		return nodeForBoolean(*object.Boolean)
   119  	} else {
   120  		return nil
   121  	}
   122  }
   123  
   124  func nodeForStringArray(array []string) *yaml.Node {
   125  	content := make([]*yaml.Node, 0)
   126  	for _, item := range array {
   127  		content = append(content, nodeForString(item))
   128  	}
   129  	return nodeForSequence(content)
   130  }
   131  
   132  func nodeForSchemaArray(array []*Schema) *yaml.Node {
   133  	content := make([]*yaml.Node, 0)
   134  	for _, item := range array {
   135  		content = append(content, item.nodeValue())
   136  	}
   137  	return nodeForSequence(content)
   138  }
   139  
   140  func (object *StringOrStringArray) nodeValue() *yaml.Node {
   141  	if object.String != nil {
   142  		return nodeForString(*object.String)
   143  	} else if object.StringArray != nil {
   144  		return nodeForStringArray(*(object.StringArray))
   145  	} else {
   146  		return nil
   147  	}
   148  }
   149  
   150  func (object *SchemaOrStringArray) nodeValue() *yaml.Node {
   151  	if object.Schema != nil {
   152  		return object.Schema.nodeValue()
   153  	} else if object.StringArray != nil {
   154  		return nodeForStringArray(*(object.StringArray))
   155  	} else {
   156  		return nil
   157  	}
   158  }
   159  
   160  func (object *SchemaOrSchemaArray) nodeValue() *yaml.Node {
   161  	if object.Schema != nil {
   162  		return object.Schema.nodeValue()
   163  	} else if object.SchemaArray != nil {
   164  		return nodeForSchemaArray(*(object.SchemaArray))
   165  	} else {
   166  		return nil
   167  	}
   168  }
   169  
   170  func (object *SchemaEnumValue) nodeValue() *yaml.Node {
   171  	if object.String != nil {
   172  		return nodeForString(*object.String)
   173  	} else if object.Bool != nil {
   174  		return nodeForBoolean(*object.Bool)
   175  	} else {
   176  		return nil
   177  	}
   178  }
   179  
   180  func nodeForNamedSchemaArray(array *[]*NamedSchema) *yaml.Node {
   181  	content := make([]*yaml.Node, 0)
   182  	for _, pair := range *(array) {
   183  		content = appendPair(content, pair.Name, pair.Value.nodeValue())
   184  	}
   185  	return nodeForMapping(content)
   186  }
   187  
   188  func nodeForNamedSchemaOrStringArray(array *[]*NamedSchemaOrStringArray) *yaml.Node {
   189  	content := make([]*yaml.Node, 0)
   190  	for _, pair := range *(array) {
   191  		content = appendPair(content, pair.Name, pair.Value.nodeValue())
   192  	}
   193  	return nodeForMapping(content)
   194  }
   195  
   196  func nodeForSchemaEnumArray(array *[]SchemaEnumValue) *yaml.Node {
   197  	content := make([]*yaml.Node, 0)
   198  	for _, item := range *array {
   199  		content = append(content, item.nodeValue())
   200  	}
   201  	return nodeForSequence(content)
   202  }
   203  
   204  func nodeForMapping(content []*yaml.Node) *yaml.Node {
   205  	return &yaml.Node{
   206  		Kind:    yaml.MappingNode,
   207  		Content: content,
   208  	}
   209  }
   210  
   211  func nodeForSequence(content []*yaml.Node) *yaml.Node {
   212  	return &yaml.Node{
   213  		Kind:    yaml.SequenceNode,
   214  		Content: content,
   215  	}
   216  }
   217  
   218  func nodeForString(value string) *yaml.Node {
   219  	return &yaml.Node{
   220  		Kind:  yaml.ScalarNode,
   221  		Tag:   "!!str",
   222  		Value: value,
   223  	}
   224  }
   225  
   226  func nodeForBoolean(value bool) *yaml.Node {
   227  	return &yaml.Node{
   228  		Kind:  yaml.ScalarNode,
   229  		Tag:   "!!bool",
   230  		Value: fmt.Sprintf("%t", value),
   231  	}
   232  }
   233  
   234  func nodeForInt64(value int64) *yaml.Node {
   235  	return &yaml.Node{
   236  		Kind:  yaml.ScalarNode,
   237  		Tag:   "!!int",
   238  		Value: fmt.Sprintf("%d", value),
   239  	}
   240  }
   241  
   242  func nodeForFloat64(value float64) *yaml.Node {
   243  	return &yaml.Node{
   244  		Kind:  yaml.ScalarNode,
   245  		Tag:   "!!float",
   246  		Value: fmt.Sprintf("%f", value),
   247  	}
   248  }
   249  
   250  func appendPair(nodes []*yaml.Node, name string, value *yaml.Node) []*yaml.Node {
   251  	nodes = append(nodes, nodeForString(name))
   252  	nodes = append(nodes, value)
   253  	return nodes
   254  }
   255  
   256  func (schema *Schema) nodeValue() *yaml.Node {
   257  	n := &yaml.Node{Kind: yaml.MappingNode}
   258  	content := make([]*yaml.Node, 0)
   259  	if schema.Title != nil {
   260  		content = appendPair(content, "title", nodeForString(*schema.Title))
   261  	}
   262  	if schema.ID != nil {
   263  		content = appendPair(content, "id", nodeForString(*schema.ID))
   264  	}
   265  	if schema.Schema != nil {
   266  		content = appendPair(content, "$schema", nodeForString(*schema.Schema))
   267  	}
   268  	if schema.Type != nil {
   269  		content = appendPair(content, "type", schema.Type.nodeValue())
   270  	}
   271  	if schema.Items != nil {
   272  		content = appendPair(content, "items", schema.Items.nodeValue())
   273  	}
   274  	if schema.Description != nil {
   275  		content = appendPair(content, "description", nodeForString(*schema.Description))
   276  	}
   277  	if schema.Required != nil {
   278  		content = appendPair(content, "required", nodeForStringArray(*schema.Required))
   279  	}
   280  	if schema.AdditionalProperties != nil {
   281  		content = appendPair(content, "additionalProperties", schema.AdditionalProperties.nodeValue())
   282  	}
   283  	if schema.PatternProperties != nil {
   284  		content = appendPair(content, "patternProperties", nodeForNamedSchemaArray(schema.PatternProperties))
   285  	}
   286  	if schema.Properties != nil {
   287  		content = appendPair(content, "properties", nodeForNamedSchemaArray(schema.Properties))
   288  	}
   289  	if schema.Dependencies != nil {
   290  		content = appendPair(content, "dependencies", nodeForNamedSchemaOrStringArray(schema.Dependencies))
   291  	}
   292  	if schema.Ref != nil {
   293  		content = appendPair(content, "$ref", nodeForString(*schema.Ref))
   294  	}
   295  	if schema.MultipleOf != nil {
   296  		content = appendPair(content, "multipleOf", schema.MultipleOf.nodeValue())
   297  	}
   298  	if schema.Maximum != nil {
   299  		content = appendPair(content, "maximum", schema.Maximum.nodeValue())
   300  	}
   301  	if schema.ExclusiveMaximum != nil {
   302  		content = appendPair(content, "exclusiveMaximum", nodeForBoolean(*schema.ExclusiveMaximum))
   303  	}
   304  	if schema.Minimum != nil {
   305  		content = appendPair(content, "minimum", schema.Minimum.nodeValue())
   306  	}
   307  	if schema.ExclusiveMinimum != nil {
   308  		content = appendPair(content, "exclusiveMinimum", nodeForBoolean(*schema.ExclusiveMinimum))
   309  	}
   310  	if schema.MaxLength != nil {
   311  		content = appendPair(content, "maxLength", nodeForInt64(*schema.MaxLength))
   312  	}
   313  	if schema.MinLength != nil {
   314  		content = appendPair(content, "minLength", nodeForInt64(*schema.MinLength))
   315  	}
   316  	if schema.Pattern != nil {
   317  		content = appendPair(content, "pattern", nodeForString(*schema.Pattern))
   318  	}
   319  	if schema.AdditionalItems != nil {
   320  		content = appendPair(content, "additionalItems", schema.AdditionalItems.nodeValue())
   321  	}
   322  	if schema.MaxItems != nil {
   323  		content = appendPair(content, "maxItems", nodeForInt64(*schema.MaxItems))
   324  	}
   325  	if schema.MinItems != nil {
   326  		content = appendPair(content, "minItems", nodeForInt64(*schema.MinItems))
   327  	}
   328  	if schema.UniqueItems != nil {
   329  		content = appendPair(content, "uniqueItems", nodeForBoolean(*schema.UniqueItems))
   330  	}
   331  	if schema.MaxProperties != nil {
   332  		content = appendPair(content, "maxProperties", nodeForInt64(*schema.MaxProperties))
   333  	}
   334  	if schema.MinProperties != nil {
   335  		content = appendPair(content, "minProperties", nodeForInt64(*schema.MinProperties))
   336  	}
   337  	if schema.Enumeration != nil {
   338  		content = appendPair(content, "enum", nodeForSchemaEnumArray(schema.Enumeration))
   339  	}
   340  	if schema.AllOf != nil {
   341  		content = appendPair(content, "allOf", nodeForSchemaArray(*schema.AllOf))
   342  	}
   343  	if schema.AnyOf != nil {
   344  		content = appendPair(content, "anyOf", nodeForSchemaArray(*schema.AnyOf))
   345  	}
   346  	if schema.OneOf != nil {
   347  		content = appendPair(content, "oneOf", nodeForSchemaArray(*schema.OneOf))
   348  	}
   349  	if schema.Not != nil {
   350  		content = appendPair(content, "not", schema.Not.nodeValue())
   351  	}
   352  	if schema.Definitions != nil {
   353  		content = appendPair(content, "definitions", nodeForNamedSchemaArray(schema.Definitions))
   354  	}
   355  	if schema.Default != nil {
   356  		// m = append(m, yaml.MapItem{Key: "default", Value: *schema.Default})
   357  	}
   358  	if schema.Format != nil {
   359  		content = appendPair(content, "format", nodeForString(*schema.Format))
   360  	}
   361  	n.Content = content
   362  	return n
   363  }
   364  
   365  // JSONString returns a json representation of a schema.
   366  func (schema *Schema) JSONString() string {
   367  	node := schema.nodeValue()
   368  	return Render(node)
   369  }
   370  

View as plain text