Codebase list golang-github-go-openapi-swag / f442b0a
Import upstream version 0.22.3 Debian Janitor 1 year, 2 months ago
13 changed file(s) with 552 addition(s) and 279 deletion(s). Raw diff Collapse all Expand all
+0
-2
.gitattributes less more
0 # gofmt always uses LF, whereas Git uses CRLF on Windows.
1 *.go text eol=lf
+0
-117
.github/CONTRIBUTING.md less more
0 ## Contribution Guidelines
1
2 ### Pull requests are always welcome
3
4 We are always thrilled to receive pull requests, and do our best to
5 process them as fast as possible. Not sure if that typo is worth a pull
6 request? Do it! We will appreciate it.
7
8 If your pull request is not accepted on the first try, don't be
9 discouraged! If there's a problem with the implementation, hopefully you
10 received feedback on what to improve.
11
12 We're trying very hard to keep go-swagger lean and focused. We don't want it
13 to do everything for everybody. This means that we might decide against
14 incorporating a new feature. However, there might be a way to implement
15 that feature *on top of* go-swagger.
16
17
18 ### Conventions
19
20 Fork the repo and make changes on your fork in a feature branch:
21
22 - If it's a bugfix branch, name it XXX-something where XXX is the number of the
23 issue
24 - If it's a feature branch, create an enhancement issue to announce your
25 intentions, and name it XXX-something where XXX is the number of the issue.
26
27 Submit unit tests for your changes. Go has a great test framework built in; use
28 it! Take a look at existing tests for inspiration. Run the full test suite on
29 your branch before submitting a pull request.
30
31 Update the documentation when creating or modifying features. Test
32 your documentation changes for clarity, concision, and correctness, as
33 well as a clean documentation build. See ``docs/README.md`` for more
34 information on building the docs and how docs get released.
35
36 Write clean code. Universally formatted code promotes ease of writing, reading,
37 and maintenance. Always run `gofmt -s -w file.go` on each changed file before
38 committing your changes. Most editors have plugins that do this automatically.
39
40 Pull requests descriptions should be as clear as possible and include a
41 reference to all the issues that they address.
42
43 Pull requests must not contain commits from other users or branches.
44
45 Commit messages must start with a capitalized and short summary (max. 50
46 chars) written in the imperative, followed by an optional, more detailed
47 explanatory text which is separated from the summary by an empty line.
48
49 Code review comments may be added to your pull request. Discuss, then make the
50 suggested modifications and push additional commits to your feature branch. Be
51 sure to post a comment after pushing. The new commits will show up in the pull
52 request automatically, but the reviewers will not be notified unless you
53 comment.
54
55 Before the pull request is merged, make sure that you squash your commits into
56 logical units of work using `git rebase -i` and `git push -f`. After every
57 commit the test suite should be passing. Include documentation changes in the
58 same commit so that a revert would remove all traces of the feature or fix.
59
60 Commits that fix or close an issue should include a reference like `Closes #XXX`
61 or `Fixes #XXX`, which will automatically close the issue when merged.
62
63 ### Sign your work
64
65 The sign-off is a simple line at the end of the explanation for the
66 patch, which certifies that you wrote it or otherwise have the right to
67 pass it on as an open-source patch. The rules are pretty simple: if you
68 can certify the below (from
69 [developercertificate.org](http://developercertificate.org/)):
70
71 ```
72 Developer Certificate of Origin
73 Version 1.1
74
75 Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
76 660 York Street, Suite 102,
77 San Francisco, CA 94110 USA
78
79 Everyone is permitted to copy and distribute verbatim copies of this
80 license document, but changing it is not allowed.
81
82
83 Developer's Certificate of Origin 1.1
84
85 By making a contribution to this project, I certify that:
86
87 (a) The contribution was created in whole or in part by me and I
88 have the right to submit it under the open source license
89 indicated in the file; or
90
91 (b) The contribution is based upon previous work that, to the best
92 of my knowledge, is covered under an appropriate open source
93 license and I have the right under that license to submit that
94 work with modifications, whether created in whole or in part
95 by me, under the same open source license (unless I am
96 permitted to submit under a different license), as indicated
97 in the file; or
98
99 (c) The contribution was provided directly to me by some other
100 person who certified (a), (b) or (c) and I have not modified
101 it.
102
103 (d) I understand and agree that this project and the contribution
104 are public and that a record of the contribution (including all
105 personal information I submit with it, including my sign-off) is
106 maintained indefinitely and may be redistributed consistent with
107 this project or the open source license(s) involved.
108 ```
109
110 then you just add a line to every git commit message:
111
112 Signed-off-by: Joe Smith <joe@gmail.com>
113
114 using your real name (sorry, no pseudonyms or anonymous contributions.)
115
116 You can add the sign off when creating the git commit via `git commit -s`.
+0
-47
.github/workflows/ci.yaml less more
0 name: Go
1
2 on: [push, pull_request]
3
4 jobs:
5 build:
6 runs-on: ${{ matrix.os }}
7
8 strategy:
9 matrix:
10 # No Windows this time. Some tests expect Unix-style paths.
11 os: [ ubuntu-latest, macos-latest ]
12 fail-fast: false
13
14 steps:
15 - uses: actions/checkout@v2
16
17 - name: Set up Go
18 uses: actions/setup-go@v2
19 with:
20 go-version: 1.17
21
22 - name: Setup gotestsum
23 uses: autero1/action-gotestsum@v1.0.0
24 with:
25 gotestsum_version: 1.7.0
26
27 - name: Test
28 run: gotestsum --format short-verbose -- -race -timeout=20m -coverprofile=coverage_txt -covermode=atomic ./...
29
30 - uses: codecov/codecov-action@v2
31 with:
32 files: coverage_txt
33
34 lint:
35 runs-on: ${{ matrix.os }}
36
37 strategy:
38 matrix:
39 os: [ ubuntu-latest, macos-latest, windows-latest ]
40 fail-fast: false
41
42 steps:
43 - uses: actions/checkout@v2
44 - uses: golangci/golangci-lint-action@v2
45 with:
46 args: --timeout=5m
+0
-4
.gitignore less more
0 secrets.yml
1 vendor
2 Godeps
3 .idea
4747 - goimports
4848 - tenv
4949 - golint
50 - exhaustruct
51 - nilnil
52 - nonamedreturns
53 - nosnakecase
1616
1717 You may also use it standalone for your projects.
1818
19 * convert between value and pointers for builtin types
20 * convert from string to builtin types (wraps strconv)
21 * fast json concatenation
22 * search in path
23 * load from file or http
24 * name mangling
25
19 - convert between value and pointers for builtin types
20 - convert from string to builtin types (wraps strconv)
21 - fast json concatenation
22 - search in path
23 - load from file or http
24 - name mangling
2625
2726 This repo has only few dependencies outside of the standard library:
2827
29 * YAML utilities depend on gopkg.in/yaml.v2
28 - YAML utilities depend on gopkg.in/yaml.v2
3029 */
3130 package swag
00 module github.com/go-openapi/swag
11
22 require (
3 github.com/davecgh/go-spew v1.1.1 // indirect
4 github.com/kr/text v0.2.0 // indirect
5 github.com/mailru/easyjson v0.7.6
6 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
7 github.com/stretchr/testify v1.6.1
8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
9 gopkg.in/yaml.v2 v2.4.0
10 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
3 github.com/mailru/easyjson v0.7.7
4 github.com/stretchr/testify v1.8.0
5 gopkg.in/yaml.v3 v3.0.1
116 )
127
13 replace github.com/golang/lint => golang.org/x/lint v0.0.0-20190409202823-959b441ac422
8 require (
9 github.com/davecgh/go-spew v1.1.1 // indirect
10 github.com/josharian/intern v1.0.0 // indirect
11 github.com/kr/text v0.2.0 // indirect
12 github.com/pmezard/go-difflib v1.0.0 // indirect
13 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
14 )
1415
15 replace sourcegraph.com/sourcegraph/go-diff => github.com/sourcegraph/go-diff v0.5.1
16 // replace github.com/golang/lint => golang.org/x/lint v0.0.0-20190409202823-959b441ac422
1617
17 go 1.11
18 // replace sourcegraph.com/sourcegraph/go-diff => github.com/sourcegraph/go-diff v0.5.1
19
20 go 1.18
33 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
44 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
55 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
6 github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
7 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
68 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
7 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
89 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
910 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
1011 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
11 github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
12 github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
13 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
14 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
12 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
13 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
1514 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1615 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
17 github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
1816 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
19 github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
20 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
17 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
18 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
19 github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
20 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
2121 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
22 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
23 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
24 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
25 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
22 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
23 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
2624 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
27 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
28 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
25 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
26 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
1515
1616 import (
1717 "fmt"
18 "io/ioutil"
18 "io"
1919 "log"
2020 "net/http"
2121 "net/url"
22 "os"
2223 "path/filepath"
2324 "runtime"
2425 "strings"
3940
4041 // LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in
4142 func LoadFromFileOrHTTP(path string) ([]byte, error) {
42 return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(path)
43 return LoadStrategy(path, os.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(path)
4344 }
4445
4546 // LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in
4647 // timeout arg allows for per request overriding of the request timeout
4748 func LoadFromFileOrHTTPWithTimeout(path string, timeout time.Duration) ([]byte, error) {
48 return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(timeout))(path)
49 return LoadStrategy(path, os.ReadFile, loadHTTPBytes(timeout))(path)
4950 }
5051
5152 // LoadStrategy returns a loader function for a given path or uri
8586 func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) {
8687 return func(path string) ([]byte, error) {
8788 client := &http.Client{Timeout: timeout}
88 req, err := http.NewRequest("GET", path, nil) // nolint: noctx
89 req, err := http.NewRequest(http.MethodGet, path, nil) //nolint:noctx
8990 if err != nil {
9091 return nil, err
9192 }
114115 return nil, fmt.Errorf("could not access document at %q [%s] ", path, resp.Status)
115116 }
116117
117 return ioutil.ReadAll(resp.Body)
118 return io.ReadAll(resp.Body)
118119 }
119120 }
1414 package swag
1515
1616 import (
17 "io/ioutil"
1817 "os"
1918 "path"
2019 "path/filepath"
2827 if tgt == "" {
2928 tgt = "pkgpaths"
3029 }
31 td, err := ioutil.TempDir("", tgt)
30 td, err := os.MkdirTemp("", tgt)
3231 if err != nil {
3332 return "", "", err
3433 }
35 td2, err := ioutil.TempDir("", tgt+"-2")
34 td2, err := os.MkdirTemp("", tgt+"-2")
3635 if err != nil {
3736 return "", "", err
3837 }
9695 assert.Empty(t, pkg)
9796 }
9897
99 // nolint: unparam
98 //nolint:unparam
10099 func assertPath(t testing.TB, expected, actual string) bool {
101100 fp, err := filepath.EvalSymlinks(expected)
102101 if assert.NoError(t, err) {
9898 )
9999
100100 // JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute):
101 // ssv: space separated value
102 // tsv: tab separated value
103 // pipes: pipe (|) separated value
104 // csv: comma separated value (default)
101 //
102 // ssv: space separated value
103 // tsv: tab separated value
104 // pipes: pipe (|) separated value
105 // csv: comma separated value (default)
105106 func JoinByFormat(data []string, format string) []string {
106107 if len(data) == 0 {
107108 return data
123124 }
124125
125126 // SplitByFormat splits a string by a known format:
126 // ssv: space separated value
127 // tsv: tab separated value
128 // pipes: pipe (|) separated value
129 // csv: comma separated value (default)
130 //
127 //
128 // ssv: space separated value
129 // tsv: tab separated value
130 // pipes: pipe (|) separated value
131 // csv: comma separated value (default)
131132 func SplitByFormat(data, format string) []string {
132133 if data == "" {
133134 return nil
2121
2222 "github.com/mailru/easyjson/jlexer"
2323 "github.com/mailru/easyjson/jwriter"
24 yaml "gopkg.in/yaml.v2"
24 yaml "gopkg.in/yaml.v3"
2525 )
2626
2727 // YAMLMatcher matches yaml
4242
4343 // BytesToYAMLDoc converts a byte slice into a YAML document
4444 func BytesToYAMLDoc(data []byte) (interface{}, error) {
45 var canary map[interface{}]interface{} // validate this is an object and not a different type
46 if err := yaml.Unmarshal(data, &canary); err != nil {
47 return nil, err
48 }
49
50 var document yaml.MapSlice // preserve order that is present in the document
45 var document yaml.Node // preserve order that is present in the document
5146 if err := yaml.Unmarshal(data, &document); err != nil {
5247 return nil, err
5348 }
54 return document, nil
49 if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode {
50 return nil, fmt.Errorf("only YAML documents that are objects are supported")
51 }
52 return &document, nil
53 }
54
55 func yamlNode(root *yaml.Node) (interface{}, error) {
56 switch root.Kind {
57 case yaml.DocumentNode:
58 return yamlDocument(root)
59 case yaml.SequenceNode:
60 return yamlSequence(root)
61 case yaml.MappingNode:
62 return yamlMapping(root)
63 case yaml.ScalarNode:
64 return yamlScalar(root)
65 case yaml.AliasNode:
66 return yamlNode(root.Alias)
67 default:
68 return nil, fmt.Errorf("unsupported YAML node type: %v", root.Kind)
69 }
70 }
71
72 func yamlDocument(node *yaml.Node) (interface{}, error) {
73 if len(node.Content) != 1 {
74 return nil, fmt.Errorf("unexpected YAML Document node content length: %d", len(node.Content))
75 }
76 return yamlNode(node.Content[0])
77 }
78
79 func yamlMapping(node *yaml.Node) (interface{}, error) {
80 m := make(JSONMapSlice, len(node.Content)/2)
81
82 var j int
83 for i := 0; i < len(node.Content); i += 2 {
84 var nmi JSONMapItem
85 k, err := yamlStringScalarC(node.Content[i])
86 if err != nil {
87 return nil, fmt.Errorf("unable to decode YAML map key: %w", err)
88 }
89 nmi.Key = k
90 v, err := yamlNode(node.Content[i+1])
91 if err != nil {
92 return nil, fmt.Errorf("unable to process YAML map value for key %q: %w", k, err)
93 }
94 nmi.Value = v
95 m[j] = nmi
96 j++
97 }
98 return m, nil
99 }
100
101 func yamlSequence(node *yaml.Node) (interface{}, error) {
102 s := make([]interface{}, 0)
103
104 for i := 0; i < len(node.Content); i++ {
105
106 v, err := yamlNode(node.Content[i])
107 if err != nil {
108 return nil, fmt.Errorf("unable to decode YAML sequence value: %w", err)
109 }
110 s = append(s, v)
111 }
112 return s, nil
113 }
114
115 const ( // See https://yaml.org/type/
116 yamlStringScalar = "tag:yaml.org,2002:str"
117 yamlIntScalar = "tag:yaml.org,2002:int"
118 yamlBoolScalar = "tag:yaml.org,2002:bool"
119 yamlFloatScalar = "tag:yaml.org,2002:float"
120 yamlTimestamp = "tag:yaml.org,2002:timestamp"
121 yamlNull = "tag:yaml.org,2002:null"
122 )
123
124 func yamlScalar(node *yaml.Node) (interface{}, error) {
125 switch node.LongTag() {
126 case yamlStringScalar:
127 return node.Value, nil
128 case yamlBoolScalar:
129 b, err := strconv.ParseBool(node.Value)
130 if err != nil {
131 return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w", node.Value, err)
132 }
133 return b, nil
134 case yamlIntScalar:
135 i, err := strconv.ParseInt(node.Value, 10, 64)
136 if err != nil {
137 return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w", node.Value, err)
138 }
139 return i, nil
140 case yamlFloatScalar:
141 f, err := strconv.ParseFloat(node.Value, 64)
142 if err != nil {
143 return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w", node.Value, err)
144 }
145 return f, nil
146 case yamlTimestamp:
147 return node.Value, nil
148 case yamlNull:
149 return nil, nil
150 default:
151 return nil, fmt.Errorf("YAML tag %q is not supported", node.LongTag())
152 }
153 }
154
155 func yamlStringScalarC(node *yaml.Node) (string, error) {
156 if node.Kind != yaml.ScalarNode {
157 return "", fmt.Errorf("expecting a string scalar but got %q", node.Kind)
158 }
159 switch node.LongTag() {
160 case yamlStringScalar, yamlIntScalar, yamlFloatScalar:
161 return node.Value, nil
162 default:
163 return "", fmt.Errorf("YAML tag %q is not supported as map key", node.LongTag())
164 }
55165 }
56166
57167 // JSONMapSlice represent a JSON object, with the order of keys maintained
102212 result = append(result, mi)
103213 }
104214 *s = result
215 }
216
217 func (s JSONMapSlice) MarshalYAML() (interface{}, error) {
218 var n yaml.Node
219 n.Kind = yaml.DocumentNode
220 var nodes []*yaml.Node
221 for _, item := range s {
222 nn, err := json2yaml(item.Value)
223 if err != nil {
224 return nil, err
225 }
226 ns := []*yaml.Node{
227 {
228 Kind: yaml.ScalarNode,
229 Tag: yamlStringScalar,
230 Value: item.Key,
231 },
232 nn,
233 }
234 nodes = append(nodes, ns...)
235 }
236
237 n.Content = []*yaml.Node{
238 {
239 Kind: yaml.MappingNode,
240 Content: nodes,
241 },
242 }
243
244 return yaml.Marshal(&n)
245 }
246
247 func json2yaml(item interface{}) (*yaml.Node, error) {
248 switch val := item.(type) {
249 case JSONMapSlice:
250 var n yaml.Node
251 n.Kind = yaml.MappingNode
252 for i := range val {
253 childNode, err := json2yaml(&val[i].Value)
254 if err != nil {
255 return nil, err
256 }
257 n.Content = append(n.Content, &yaml.Node{
258 Kind: yaml.ScalarNode,
259 Tag: yamlStringScalar,
260 Value: val[i].Key,
261 }, childNode)
262 }
263 return &n, nil
264 case map[string]interface{}:
265 var n yaml.Node
266 n.Kind = yaml.MappingNode
267 for k, v := range val {
268 childNode, err := json2yaml(v)
269 if err != nil {
270 return nil, err
271 }
272 n.Content = append(n.Content, &yaml.Node{
273 Kind: yaml.ScalarNode,
274 Tag: yamlStringScalar,
275 Value: k,
276 }, childNode)
277 }
278 return &n, nil
279 case []interface{}:
280 var n yaml.Node
281 n.Kind = yaml.SequenceNode
282 for i := range val {
283 childNode, err := json2yaml(val[i])
284 if err != nil {
285 return nil, err
286 }
287 n.Content = append(n.Content, childNode)
288 }
289 return &n, nil
290 case string:
291 return &yaml.Node{
292 Kind: yaml.ScalarNode,
293 Tag: yamlStringScalar,
294 Value: val,
295 }, nil
296 case float64:
297 return &yaml.Node{
298 Kind: yaml.ScalarNode,
299 Tag: yamlFloatScalar,
300 Value: strconv.FormatFloat(val, 'f', -1, 64),
301 }, nil
302 case int64:
303 return &yaml.Node{
304 Kind: yaml.ScalarNode,
305 Tag: yamlIntScalar,
306 Value: strconv.FormatInt(val, 10),
307 }, nil
308 case uint64:
309 return &yaml.Node{
310 Kind: yaml.ScalarNode,
311 Tag: yamlIntScalar,
312 Value: strconv.FormatUint(val, 10),
313 }, nil
314 case bool:
315 return &yaml.Node{
316 Kind: yaml.ScalarNode,
317 Tag: yamlBoolScalar,
318 Value: strconv.FormatBool(val),
319 }, nil
320 }
321 return nil, nil
105322 }
106323
107324 // JSONMapItem represents the value of a key in a JSON object held by JSONMapSlice
172389 }
173390
174391 switch in := input.(type) {
175 case yaml.MapSlice:
176
177 o := make(JSONMapSlice, len(in))
178 for i, mi := range in {
179 var nmi JSONMapItem
180 if nmi.Key, err = format(mi.Key); err != nil {
181 return nil, err
182 }
183
184 v, ert := transformData(mi.Value)
185 if ert != nil {
186 return nil, ert
187 }
188 nmi.Value = v
189 o[i] = nmi
190 }
191 return o, nil
392 case yaml.Node:
393 return yamlNode(&in)
394 case *yaml.Node:
395 return yamlNode(in)
192396 case map[interface{}]interface{}:
193397 o := make(JSONMapSlice, 0, len(in))
194398 for ke, va := range in {
1919 "testing"
2020
2121 "github.com/stretchr/testify/assert"
22 yaml "gopkg.in/yaml.v2"
22 "github.com/stretchr/testify/require"
23 yaml "gopkg.in/yaml.v3"
2324 )
2425
25 /* currently unused:
26 type failJSONMarshal struct {
26 func TestJSONToYAML(t *testing.T) {
27 sd := `{"1":"the int key value","name":"a string value","y":"some value"}`
28 var data JSONMapSlice
29 require.NoError(t, json.Unmarshal([]byte(sd), &data))
30
31 y, err := data.MarshalYAML()
32 require.NoError(t, err)
33 const expected = `"1": the int key value
34 name: a string value
35 y: some value
36 `
37 assert.Equal(t, expected, string(y.([]byte)))
38
39 nstd := `{"1":"the int key value","name":"a string value","y":"some value","tag":{"name":"tag name"}}`
40 const nestpected = `"1": the int key value
41 name: a string value
42 y: some value
43 tag:
44 name: tag name
45 `
46 var ndata JSONMapSlice
47 require.NoError(t, json.Unmarshal([]byte(nstd), &ndata))
48 ny, err := ndata.MarshalYAML()
49 require.NoError(t, err)
50 assert.Equal(t, nestpected, string(ny.([]byte)))
51
52 ydoc, err := BytesToYAMLDoc([]byte(fixtures2224))
53 require.NoError(t, err)
54 b, err := YAMLToJSON(ydoc)
55 require.NoError(t, err)
56
57 var bdata JSONMapSlice
58 require.NoError(t, json.Unmarshal(b, &bdata))
59
2760 }
28
29 func (f failJSONMarshal) MarshalJSON() ([]byte, error) {
30 return nil, errors.New("expected")
31 }
32 */
3361
3462 func TestYAMLToJSON(t *testing.T) {
3563
3866 name: a string value
3967 'y': some value
4068 `
41 var data yaml.MapSlice
69 var data yaml.Node
4270 _ = yaml.Unmarshal([]byte(sd), &data)
4371
4472 d, err := YAMLToJSON(data)
4674 assert.Equal(t, `{"1":"the int key value","name":"a string value","y":"some value"}`, string(d))
4775 }
4876
49 data = append(data, yaml.MapItem{Key: true, Value: "the bool value"})
77 ns := []*yaml.Node{
78 {
79 Kind: yaml.ScalarNode,
80 Value: "true",
81 Tag: "!!bool",
82 },
83 {
84 Kind: yaml.ScalarNode,
85 Value: "the bool value",
86 Tag: "!!str",
87 },
88 }
89 data.Content[0].Content = append(data.Content[0].Content, ns...)
5090 d, err = YAMLToJSON(data)
5191 assert.Error(t, err)
5292 assert.Nil(t, d)
5393
54 data = data[:len(data)-1]
55
56 tag := yaml.MapSlice{{Key: "name", Value: "tag name"}}
57 data = append(data, yaml.MapItem{Key: "tag", Value: tag})
94 data.Content[0].Content = data.Content[0].Content[:len(data.Content[0].Content)-2]
95
96 tag := []*yaml.Node{
97 {
98 Kind: yaml.ScalarNode,
99 Value: "tag",
100 Tag: "!!str",
101 },
102 {
103 Kind: yaml.MappingNode,
104 Content: []*yaml.Node{
105 {
106 Kind: yaml.ScalarNode,
107 Value: "name",
108 Tag: "!!str",
109 },
110 {
111 Kind: yaml.ScalarNode,
112 Value: "tag name",
113 Tag: "!!str",
114 },
115 },
116 },
117 }
118 data.Content[0].Content = append(data.Content[0].Content, tag...)
58119
59120 d, err = YAMLToJSON(data)
60121 assert.NoError(t, err)
61122 assert.Equal(t, `{"1":"the int key value","name":"a string value","y":"some value","tag":{"name":"tag name"}}`, string(d))
62123
63 tag = yaml.MapSlice{{Key: true, Value: "bool tag name"}}
64 data = append(data[:len(data)-1], yaml.MapItem{Key: "tag", Value: tag})
124 tag[1].Content = []*yaml.Node{
125 {
126 Kind: yaml.ScalarNode,
127 Value: "true",
128 Tag: "!!bool",
129 },
130 {
131 Kind: yaml.ScalarNode,
132 Value: "the bool tag name",
133 Tag: "!!str",
134 },
135 }
65136
66137 d, err = YAMLToJSON(data)
67138 assert.Error(t, err)
103174 doc, err := BytesToYAMLDoc([]byte(withYKey))
104175 if assert.NoError(t, err) {
105176 _, err := YAMLToJSON(doc)
106 if assert.Error(t, err) {
177 if assert.NoError(t, err) {
107178 doc, err := BytesToYAMLDoc([]byte(withQuotedYKey))
108179 if assert.NoError(t, err) {
109180 jsond, err := YAMLToJSON(doc)
130201 }
131202
132203 func TestMapKeyTypes(t *testing.T) {
133 d := yaml.MapSlice{
134 yaml.MapItem{Key: 12345, Value: "int"},
135 yaml.MapItem{Key: int8(1), Value: "int8"},
136 yaml.MapItem{Key: int16(12345), Value: "int16"},
137 yaml.MapItem{Key: int32(12345678), Value: "int32"},
138 yaml.MapItem{Key: int64(12345678910), Value: "int64"},
139 yaml.MapItem{Key: uint(12345), Value: "uint"},
140 yaml.MapItem{Key: uint8(1), Value: "uint8"},
141 yaml.MapItem{Key: uint16(12345), Value: "uint16"},
142 yaml.MapItem{Key: uint32(12345678), Value: "uint32"},
143 yaml.MapItem{Key: uint64(12345678910), Value: "uint64"},
144 }
145 _, err := YAMLToJSON(d)
146 assert.NoError(t, err)
147
148204 dm := map[interface{}]interface{}{
149205 12345: "int",
150206 int8(1): "int8",
157213 uint32(12345678): "uint32",
158214 uint64(12345678910): "uint64",
159215 }
160 _, err = YAMLToJSON(dm)
216 _, err := YAMLToJSON(dm)
161217 assert.NoError(t, err)
162218 }
219
220 const fixtures2224 = `definitions:
221 Time:
222 type: string
223 format: date-time
224 x-go-type:
225 import:
226 package: time
227 embedded: true
228 type: Time
229 x-nullable: true
230
231 TimeAsObject: # <- time.Time is actually a struct
232 type: string
233 format: date-time
234 x-go-type:
235 import:
236 package: time
237 hints:
238 kind: object
239 embedded: true
240 type: Time
241 x-nullable: true
242
243 Raw:
244 x-go-type:
245 import:
246 package: encoding/json
247 hints:
248 kind: primitive
249 embedded: true
250 type: RawMessage
251
252 Request:
253 x-go-type:
254 import:
255 package: net/http
256 hints:
257 kind: object
258 embedded: true
259 type: Request
260
261 RequestPointer:
262 x-go-type:
263 import:
264 package: net/http
265 hints:
266 kind: object
267 nullable: true
268 embedded: true
269 type: Request
270
271 OldStyleImport:
272 type: object
273 x-go-type:
274 import:
275 package: net/http
276 type: Request
277 hints:
278 noValidation: true
279
280 OldStyleRenamed:
281 type: object
282 x-go-type:
283 import:
284 package: net/http
285 type: Request
286 hints:
287 noValidation: true
288 x-go-name: OldRenamed
289
290 ObjectWithEmbedded:
291 type: object
292 properties:
293 a:
294 $ref: '#/definitions/Time'
295 b:
296 $ref: '#/definitions/Request'
297 c:
298 $ref: '#/definitions/TimeAsObject'
299 d:
300 $ref: '#/definitions/Raw'
301 e:
302 $ref: '#/definitions/JSONObject'
303 f:
304 $ref: '#/definitions/JSONMessage'
305 g:
306 $ref: '#/definitions/JSONObjectWithAlias'
307
308 ObjectWithExternals:
309 type: object
310 properties:
311 a:
312 $ref: '#/definitions/OldStyleImport'
313 b:
314 $ref: '#/definitions/OldStyleRenamed'
315
316 Base:
317 properties: &base
318 id:
319 type: integer
320 format: uint64
321 x-go-custom-tag: 'gorm:"primary_key"'
322 FBID:
323 type: integer
324 format: uint64
325 x-go-custom-tag: 'gorm:"index"'
326 created_at:
327 $ref: "#/definitions/Time"
328 updated_at:
329 $ref: "#/definitions/Time"
330 version:
331 type: integer
332 format: uint64
333
334 HotspotType:
335 type: string
336 enum:
337 - A
338 - B
339 - C
340
341 Hotspot:
342 type: object
343 allOf:
344 - properties: *base
345 - properties:
346 access_points:
347 type: array
348 items:
349 $ref: '#/definitions/AccessPoint'
350 type:
351 $ref: '#/definitions/HotspotType'
352 required:
353 - type
354
355 AccessPoint:
356 type: object
357 allOf:
358 - properties: *base
359 - properties:
360 mac_address:
361 type: string
362 x-go-custom-tag: 'gorm:"index;not null;unique"'
363 hotspot_id:
364 type: integer
365 format: uint64
366 hotspot:
367 $ref: '#/definitions/Hotspot'
368
369 JSONObject:
370 type: object
371 additionalProperties:
372 type: array
373 items:
374 $ref: '#/definitions/Raw'
375
376 JSONObjectWithAlias:
377 type: object
378 additionalProperties:
379 type: object
380 properties:
381 message:
382 $ref: '#/definitions/JSONMessage'
383
384 JSONMessage:
385 $ref: '#/definitions/Raw'
386
387 Incorrect:
388 x-go-type:
389 import:
390 package: net
391 hints:
392 kind: array
393 embedded: true
394 type: Buffers
395 x-nullable: true
396 `
163397
164398 const withQuotedYKey = `consumes:
165399 - application/json