1 // Copyright 2015 go-swagger maintainers
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
23 "github.com/mailru/easyjson/jlexer"
24 "github.com/mailru/easyjson/jwriter"
25 yaml "gopkg.in/yaml.v2"
28 // YAMLMatcher matches yaml
29 func YAMLMatcher(path string) bool {
30 ext := filepath.Ext(path)
31 return ext == ".yaml" || ext == ".yml"
34 // YAMLToJSON converts YAML unmarshaled data into json compatible data
35 func YAMLToJSON(data interface{}) (json.RawMessage, error) {
36 jm, err := transformData(data)
40 b, err := WriteJSON(jm)
41 return json.RawMessage(b), err
44 // BytesToYAMLDoc converts a byte slice into a YAML document
45 func BytesToYAMLDoc(data []byte) (interface{}, error) {
46 var canary map[interface{}]interface{} // validate this is an object and not a different type
47 if err := yaml.Unmarshal(data, &canary); err != nil {
51 var document yaml.MapSlice // preserve order that is present in the document
52 if err := yaml.Unmarshal(data, &document); err != nil {
58 // JSONMapSlice represent a JSON object, with the order of keys maintained
59 type JSONMapSlice []JSONMapItem
61 // MarshalJSON renders a JSONMapSlice as JSON
62 func (s JSONMapSlice) MarshalJSON() ([]byte, error) {
63 w := &jwriter.Writer{Flags: jwriter.NilMapAsEmpty | jwriter.NilSliceAsEmpty}
68 // MarshalEasyJSON renders a JSONMapSlice as JSON, using easyJSON
69 func (s JSONMapSlice) MarshalEasyJSON(w *jwriter.Writer) {
74 for i := 0; i < ln; i++ {
75 s[i].MarshalEasyJSON(w)
76 if i != last { // last item
84 // UnmarshalJSON makes a JSONMapSlice from JSON
85 func (s *JSONMapSlice) UnmarshalJSON(data []byte) error {
86 l := jlexer.Lexer{Data: data}
87 s.UnmarshalEasyJSON(&l)
91 // UnmarshalEasyJSON makes a JSONMapSlice from JSON, using easyJSON
92 func (s *JSONMapSlice) UnmarshalEasyJSON(in *jlexer.Lexer) {
98 var result JSONMapSlice
100 for !in.IsDelim('}') {
102 mi.UnmarshalEasyJSON(in)
103 result = append(result, mi)
108 // JSONMapItem represents the value of a key in a JSON object held by JSONMapSlice
109 type JSONMapItem struct {
114 // MarshalJSON renders a JSONMapItem as JSON
115 func (s JSONMapItem) MarshalJSON() ([]byte, error) {
116 w := &jwriter.Writer{Flags: jwriter.NilMapAsEmpty | jwriter.NilSliceAsEmpty}
118 return w.BuildBytes()
121 // MarshalEasyJSON renders a JSONMapItem as JSON, using easyJSON
122 func (s JSONMapItem) MarshalEasyJSON(w *jwriter.Writer) {
125 w.Raw(WriteJSON(s.Value))
128 // UnmarshalJSON makes a JSONMapItem from JSON
129 func (s *JSONMapItem) UnmarshalJSON(data []byte) error {
130 l := jlexer.Lexer{Data: data}
131 s.UnmarshalEasyJSON(&l)
135 // UnmarshalEasyJSON makes a JSONMapItem from JSON, using easyJSON
136 func (s *JSONMapItem) UnmarshalEasyJSON(in *jlexer.Lexer) {
137 key := in.UnsafeString()
139 value := in.Interface()
145 func transformData(input interface{}) (out interface{}, err error) {
146 switch in := input.(type) {
149 o := make(JSONMapSlice, len(in))
150 for i, mi := range in {
152 switch k := mi.Key.(type) {
156 nmi.Key = strconv.Itoa(k)
158 return nil, fmt.Errorf("types don't match expect map key string or int got: %T", mi.Key)
161 v, ert := transformData(mi.Value)
169 case map[interface{}]interface{}:
170 o := make(JSONMapSlice, 0, len(in))
171 for ke, va := range in {
173 switch k := ke.(type) {
177 nmi.Key = strconv.Itoa(k)
179 return nil, fmt.Errorf("types don't match expect map key string or int got: %T", ke)
182 v, ert := transformData(va)
192 o := make([]interface{}, len1)
193 for i := 0; i < len1; i++ {
194 o[i], err = transformData(in[i])
204 // YAMLDoc loads a yaml document from either http or a file and converts it to json
205 func YAMLDoc(path string) (json.RawMessage, error) {
206 yamlDoc, err := YAMLData(path)
211 data, err := YAMLToJSON(yamlDoc)
219 // YAMLData loads a yaml document from either http or a file
220 func YAMLData(path string) (interface{}, error) {
221 data, err := LoadFromFileOrHTTP(path)
226 return BytesToYAMLDoc(data)