github.com/jasonfriedland/openapi2proto@v0.2.1/openapi/schema.go (about) 1 package openapi 2 3 import ( 4 "encoding/json" 5 "reflect" 6 7 "github.com/pkg/errors" 8 ) 9 10 // Using reflect is reaaaaaal slow, so we should really be generating 11 // code, but I'm going to punt it for now 12 var schemaProxyType reflect.Type 13 14 func init() { 15 rt := reflect.TypeOf(Schema{}) 16 var fields []reflect.StructField 17 for i := 0; i < rt.NumField(); i++ { 18 ft := rt.Field(i) 19 if ft.PkgPath != "" { 20 continue 21 } 22 fields = append(fields, ft) 23 } 24 25 schemaProxyType = reflect.StructOf(fields) 26 } 27 28 // UnmarshalJSON decodes JSON data into a Schema 29 func (s *Schema) UnmarshalJSON(data []byte) error { 30 var b bool 31 if err := json.Unmarshal(data, &b); err == nil { 32 if b { 33 *s = Schema{} 34 } else { 35 *s = Schema{isNil: true} 36 } 37 return nil 38 } 39 40 nv := reflect.New(schemaProxyType) 41 42 if err := json.Unmarshal(data, nv.Interface()); err != nil { 43 return errors.Wrap(err, `failed to unmarshal JSON`) 44 } 45 46 nv = nv.Elem() 47 sv := reflect.ValueOf(s).Elem() 48 for i := 0; i < nv.NumField(); i++ { 49 ft := nv.Type().Field(i) 50 fv := nv.Field(i) 51 sv.FieldByName(ft.Name).Set(fv) 52 } 53 54 return nil 55 } 56 57 // IsNil returns true if it's nil schema (e.g.: `additionalProperties: false`) 58 func (s Schema) IsNil() bool { 59 return s.isNil 60 } 61 62 // UnmarshalJSON decodes JSON data into a SchemaType 63 func (s *SchemaType) UnmarshalJSON(data []byte) error { 64 var str string 65 if err := json.Unmarshal(data, &str); err == nil { 66 *s = []string{str} 67 return nil 68 } 69 70 var l []string 71 if err := json.Unmarshal(data, &l); err == nil { 72 *s = l 73 return nil 74 } 75 76 return errors.Errorf(`invalid type '%s'`, data) 77 } 78 79 // UnmarshalYAML decodes YAML data into a SchemaType 80 func (s *SchemaType) UnmarshalYAML(unmarshal func(interface{}) error) error { 81 var str string 82 if err := unmarshal(&str); err == nil { 83 if str == "" { 84 *s = []string(nil) 85 } else { 86 *s = []string{str} 87 } 88 return nil 89 } 90 91 var l []string 92 if err := unmarshal(&l); err == nil { 93 *s = l 94 return nil 95 } 96 97 return errors.New(`invalid type for schema type`) 98 } 99 100 // Empty returns true if there was no type specified 101 func (s *SchemaType) Empty() bool { 102 return len(*s) == 0 103 } 104 105 // Contains returns true if the specified type is listed within 106 // the list of schema types 107 func (s *SchemaType) Contains(t string) bool { 108 for _, v := range *s { 109 if v == t { 110 return true 111 } 112 } 113 return false 114 } 115 116 // Len returns the number of types listed under this SchemaType 117 func (s *SchemaType) Len() int { 118 return len(*s) 119 } 120 121 // First returns the first type listed under this SchemaType 122 func (s *SchemaType) First() string { 123 if !s.Empty() { 124 return (*s)[0] 125 } 126 return "" 127 } 128