@@ -3,6 +3,7 @@ package main
33import (
44 "bytes"
55 "encoding/json"
6+ "errors"
67 "fmt"
78 "io"
89 "io/ioutil"
@@ -20,11 +21,11 @@ type schema struct {
2021 Title string `json:"title,omitempty"`
2122 Description string `json:"description,omitempty"`
2223 Required []string `json:"required,omitempty"`
23- Type string `json:"type,omitempty"`
24+ Type PropertyTypes `json:"type,omitempty"`
2425 Properties map [string ]* schema `json:"properties,omitempty"`
2526 Items * schema `json:"items,omitempty"`
2627 Definitions map [string ]* schema `json:"definitions,omitempty"`
27- Enum []string `json:"enum"`
28+ Enum []Any `json:"enum"`
2829}
2930
3031func newSchema (r io.Reader , workingDir string ) (* schema , error ) {
@@ -104,16 +105,16 @@ func findDefinitions(s *schema) []*schema {
104105
105106 for k , p := range s .Properties {
106107 // Use the identifier as the title.
107- if p .Type == "object" {
108+ if p .Type . HasType ( PropertyTypeObject ) {
108109 p .Title = k
109110 objs = append (objs , p )
110111 }
111112
112113 // If the property is an array of objects, use the name of the array
113114 // property as the title.
114- if p .Type == "array" {
115+ if p .Type . HasType ( PropertyTypeArray ) {
115116 if p .Items != nil {
116- if p .Items .Type == "object" {
117+ if p .Items .Type . HasType ( PropertyTypeObject ) {
117118 p .Items .Title = k
118119 objs = append (objs , p .Items )
119120 }
@@ -143,22 +144,35 @@ func printProperties(w io.Writer, s *schema) {
143144
144145 for k , p := range s .Properties {
145146 // Generate relative links for objects and arrays of objects.
146- var propType string
147- switch p .Type {
148- case "object" :
149- propType = fmt .Sprintf ("[%s](#%s)" , p .Type , strings .ToLower (k ))
150- case "array" :
151- if p .Items != nil {
152- if p .Items .Type == "object" {
153- propType = fmt .Sprintf ("[%s](#%s)[]" , p .Items .Type , strings .ToLower (k ))
147+ var propType []string
148+ for _ , pt := range p .Type {
149+ switch pt {
150+ case PropertyTypeObject :
151+ propType = append (propType , fmt .Sprintf ("[object](#%s)" , strings .ToLower (k )))
152+ case PropertyTypeArray :
153+ if p .Items != nil {
154+ for _ , pi := range p .Items .Type {
155+ if pi == PropertyTypeObject {
156+ propType = append (propType , fmt .Sprintf ("[%s](#%s)[]" , pi , strings .ToLower (k )))
157+ } else {
158+ propType = append (propType , fmt .Sprintf ("%s[]" , pi ))
159+ }
160+ }
154161 } else {
155- propType = fmt . Sprintf ( "%s[]" , p . Items . Type )
162+ propType = append ( propType , string ( pt ) )
156163 }
157- } else {
158- propType = p . Type
164+ default :
165+ propType = append ( propType , string ( pt ))
159166 }
160- default :
161- propType = p .Type
167+ }
168+
169+ var propTypeStr string
170+ if len (propType ) == 1 {
171+ propTypeStr = propType [0 ]
172+ } else if len (propType ) == 2 {
173+ propTypeStr = strings .Join (propType , " or " )
174+ } else if len (propType ) > 2 {
175+ propTypeStr = fmt .Sprintf ("%s, or %s" , strings .Join (propType [:len (propType )- 1 ], ", " ), propType [len (propType )- 1 ])
162176 }
163177
164178 // Emphasize required properties.
@@ -172,10 +186,14 @@ func printProperties(w io.Writer, s *schema) {
172186 desc := p .Description
173187
174188 if len (p .Enum ) > 0 {
175- desc += " Possible values are: `" + strings .Join (p .Enum , "`, `" ) + "`."
189+ var vals []string
190+ for _ , e := range p .Enum {
191+ vals = append (vals , e .String ())
192+ }
193+ desc += " Possible values are: `" + strings .Join (vals , "`, `" ) + "`."
176194 }
177195
178- rows = append (rows , []string {fmt .Sprintf ("`%s`" , k ), propType , required , strings .TrimSpace (desc )})
196+ rows = append (rows , []string {fmt .Sprintf ("`%s`" , k ), propTypeStr , required , strings .TrimSpace (desc )})
179197 }
180198
181199 // Sort by the required column, then by the name column.
@@ -202,3 +220,67 @@ func in(strs []string, str string) bool {
202220 }
203221 return false
204222}
223+
224+ type PropertyTypes []PropertyType
225+
226+ func (pts * PropertyTypes ) HasType (pt PropertyType ) bool {
227+ for _ , t := range * pts {
228+ if t == pt {
229+ return true
230+ }
231+ }
232+ return false
233+ }
234+
235+ func (pt * PropertyTypes ) UnmarshalJSON (data []byte ) error {
236+ var value interface {}
237+ if err := json .Unmarshal (data , & value ); err != nil {
238+ return err
239+ }
240+
241+ switch val := value .(type ) {
242+ case string :
243+ * pt = []PropertyType {PropertyType (val )}
244+ return nil
245+ case []interface {}:
246+ var pts []PropertyType
247+ for _ , t := range val {
248+ s , ok := t .(string )
249+ if ! ok {
250+ return errors .New ("unsupported property type" )
251+ }
252+ pts = append (pts , PropertyType (s ))
253+ }
254+ * pt = pts
255+ default :
256+ return errors .New ("unsupported property type" )
257+ }
258+
259+ return nil
260+ }
261+
262+ type PropertyType string
263+
264+ const (
265+ PropertyTypeString PropertyType = "string"
266+ PropertyTypeNumber PropertyType = "number"
267+ PropertyTypeBoolean PropertyType = "boolean"
268+ PropertyTypeObject PropertyType = "object"
269+ PropertyTypeArray PropertyType = "array"
270+ PropertyTypeNull PropertyType = "null"
271+ )
272+
273+ type Any struct {
274+ value interface {}
275+ }
276+
277+ func (u * Any ) UnmarshalJSON (data []byte ) error {
278+ if err := json .Unmarshal (data , & u .value ); err != nil {
279+ return err
280+ }
281+ return nil
282+ }
283+
284+ func (u * Any ) String () string {
285+ return fmt .Sprintf ("%v" , u .value )
286+ }
0 commit comments