paths.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2015 go-swagger maintainers
  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. package spec
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "strings"
  19. "github.com/go-openapi/swag"
  20. "k8s.io/kube-openapi/pkg/internal"
  21. jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
  22. )
  23. // Paths holds the relative paths to the individual endpoints.
  24. // The path is appended to the [`basePath`](http://goo.gl/8us55a#swaggerBasePath) in order
  25. // to construct the full URL.
  26. // The Paths may be empty, due to [ACL constraints](http://goo.gl/8us55a#securityFiltering).
  27. //
  28. // For more information: http://goo.gl/8us55a#pathsObject
  29. type Paths struct {
  30. VendorExtensible
  31. Paths map[string]PathItem `json:"-"` // custom serializer to flatten this, each entry must start with "/"
  32. }
  33. // UnmarshalJSON hydrates this items instance with the data from JSON
  34. func (p *Paths) UnmarshalJSON(data []byte) error {
  35. if internal.UseOptimizedJSONUnmarshaling {
  36. return jsonv2.Unmarshal(data, p)
  37. }
  38. var res map[string]json.RawMessage
  39. if err := json.Unmarshal(data, &res); err != nil {
  40. return err
  41. }
  42. for k, v := range res {
  43. if strings.HasPrefix(strings.ToLower(k), "x-") {
  44. if p.Extensions == nil {
  45. p.Extensions = make(map[string]interface{})
  46. }
  47. var d interface{}
  48. if err := json.Unmarshal(v, &d); err != nil {
  49. return err
  50. }
  51. p.Extensions[k] = d
  52. }
  53. if strings.HasPrefix(k, "/") {
  54. if p.Paths == nil {
  55. p.Paths = make(map[string]PathItem)
  56. }
  57. var pi PathItem
  58. if err := json.Unmarshal(v, &pi); err != nil {
  59. return err
  60. }
  61. p.Paths[k] = pi
  62. }
  63. }
  64. return nil
  65. }
  66. func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
  67. tok, err := dec.ReadToken()
  68. if err != nil {
  69. return err
  70. }
  71. var ext any
  72. var pi PathItem
  73. switch k := tok.Kind(); k {
  74. case 'n':
  75. return nil // noop
  76. case '{':
  77. for {
  78. tok, err := dec.ReadToken()
  79. if err != nil {
  80. return err
  81. }
  82. if tok.Kind() == '}' {
  83. return nil
  84. }
  85. switch k := tok.String(); {
  86. case internal.IsExtensionKey(k):
  87. ext = nil
  88. if err := opts.UnmarshalNext(dec, &ext); err != nil {
  89. return err
  90. }
  91. if p.Extensions == nil {
  92. p.Extensions = make(map[string]any)
  93. }
  94. p.Extensions[k] = ext
  95. case len(k) > 0 && k[0] == '/':
  96. pi = PathItem{}
  97. if err := opts.UnmarshalNext(dec, &pi); err != nil {
  98. return err
  99. }
  100. if p.Paths == nil {
  101. p.Paths = make(map[string]PathItem)
  102. }
  103. p.Paths[k] = pi
  104. default:
  105. _, err := dec.ReadValue() // skip value
  106. if err != nil {
  107. return err
  108. }
  109. }
  110. }
  111. default:
  112. return fmt.Errorf("unknown JSON kind: %v", k)
  113. }
  114. }
  115. // MarshalJSON converts this items object to JSON
  116. func (p Paths) MarshalJSON() ([]byte, error) {
  117. if internal.UseOptimizedJSONMarshaling {
  118. return internal.DeterministicMarshal(p)
  119. }
  120. b1, err := json.Marshal(p.VendorExtensible)
  121. if err != nil {
  122. return nil, err
  123. }
  124. pths := make(map[string]PathItem)
  125. for k, v := range p.Paths {
  126. if strings.HasPrefix(k, "/") {
  127. pths[k] = v
  128. }
  129. }
  130. b2, err := json.Marshal(pths)
  131. if err != nil {
  132. return nil, err
  133. }
  134. concated := swag.ConcatJSON(b1, b2)
  135. return concated, nil
  136. }
  137. func (p Paths) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
  138. m := make(map[string]any, len(p.Extensions)+len(p.Paths))
  139. for k, v := range p.Extensions {
  140. if internal.IsExtensionKey(k) {
  141. m[k] = v
  142. }
  143. }
  144. for k, v := range p.Paths {
  145. if strings.HasPrefix(k, "/") {
  146. m[k] = v
  147. }
  148. }
  149. return opts.MarshalNext(enc, m)
  150. }