utils.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
  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. // author xeipuuv
  15. // author-github https://github.com/xeipuuv
  16. // author-mail [email protected]
  17. //
  18. // repository-name gojsonschema
  19. // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language.
  20. //
  21. // description Various utility functions.
  22. //
  23. // created 26-02-2013
  24. package gojsonschema
  25. import (
  26. "encoding/json"
  27. "fmt"
  28. "math"
  29. "reflect"
  30. "strconv"
  31. )
  32. func isKind(what interface{}, kind reflect.Kind) bool {
  33. target := what
  34. if isJsonNumber(what) {
  35. // JSON Numbers are strings!
  36. target = *mustBeNumber(what)
  37. }
  38. return reflect.ValueOf(target).Kind() == kind
  39. }
  40. func existsMapKey(m map[string]interface{}, k string) bool {
  41. _, ok := m[k]
  42. return ok
  43. }
  44. func isStringInSlice(s []string, what string) bool {
  45. for i := range s {
  46. if s[i] == what {
  47. return true
  48. }
  49. }
  50. return false
  51. }
  52. func marshalToJsonString(value interface{}) (*string, error) {
  53. mBytes, err := json.Marshal(value)
  54. if err != nil {
  55. return nil, err
  56. }
  57. sBytes := string(mBytes)
  58. return &sBytes, nil
  59. }
  60. func isJsonNumber(what interface{}) bool {
  61. switch what.(type) {
  62. case json.Number:
  63. return true
  64. }
  65. return false
  66. }
  67. func checkJsonNumber(what interface{}) (isValidFloat64 bool, isValidInt64 bool, isValidInt32 bool) {
  68. jsonNumber := what.(json.Number)
  69. f64, errFloat64 := jsonNumber.Float64()
  70. s64 := strconv.FormatFloat(f64, 'f', -1, 64)
  71. _, errInt64 := strconv.ParseInt(s64, 10, 64)
  72. isValidFloat64 = errFloat64 == nil
  73. isValidInt64 = errInt64 == nil
  74. _, errInt32 := strconv.ParseInt(s64, 10, 32)
  75. isValidInt32 = isValidInt64 && errInt32 == nil
  76. return
  77. }
  78. // same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER
  79. const (
  80. max_json_float = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1
  81. min_json_float = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1
  82. )
  83. func isFloat64AnInteger(f float64) bool {
  84. if math.IsNaN(f) || math.IsInf(f, 0) || f < min_json_float || f > max_json_float {
  85. return false
  86. }
  87. return f == float64(int64(f)) || f == float64(uint64(f))
  88. }
  89. func mustBeInteger(what interface{}) *int {
  90. if isJsonNumber(what) {
  91. number := what.(json.Number)
  92. _, _, isValidInt32 := checkJsonNumber(number)
  93. if isValidInt32 {
  94. int64Value, err := number.Int64()
  95. if err != nil {
  96. return nil
  97. }
  98. int32Value := int(int64Value)
  99. return &int32Value
  100. } else {
  101. return nil
  102. }
  103. }
  104. return nil
  105. }
  106. func mustBeNumber(what interface{}) *float64 {
  107. if isJsonNumber(what) {
  108. number := what.(json.Number)
  109. float64Value, err := number.Float64()
  110. if err == nil {
  111. return &float64Value
  112. } else {
  113. return nil
  114. }
  115. }
  116. return nil
  117. }
  118. // formats a number so that it is displayed as the smallest string possible
  119. func resultErrorFormatJsonNumber(n json.Number) string {
  120. if int64Value, err := n.Int64(); err == nil {
  121. return fmt.Sprintf("%d", int64Value)
  122. }
  123. float64Value, _ := n.Float64()
  124. return fmt.Sprintf("%g", float64Value)
  125. }
  126. // formats a number so that it is displayed as the smallest string possible
  127. func resultErrorFormatNumber(n float64) string {
  128. if isFloat64AnInteger(n) {
  129. return fmt.Sprintf("%d", int64(n))
  130. }
  131. return fmt.Sprintf("%g", n)
  132. }
  133. func convertDocumentNode(val interface{}) interface{} {
  134. if lval, ok := val.([]interface{}); ok {
  135. res := []interface{}{}
  136. for _, v := range lval {
  137. res = append(res, convertDocumentNode(v))
  138. }
  139. return res
  140. }
  141. if mval, ok := val.(map[interface{}]interface{}); ok {
  142. res := map[string]interface{}{}
  143. for k, v := range mval {
  144. res[k.(string)] = convertDocumentNode(v)
  145. }
  146. return res
  147. }
  148. return val
  149. }