utils.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. return reflect.ValueOf(what).Kind() == kind
  34. }
  35. func existsMapKey(m map[string]interface{}, k string) bool {
  36. _, ok := m[k]
  37. return ok
  38. }
  39. func isStringInSlice(s []string, what string) bool {
  40. for i := range s {
  41. if s[i] == what {
  42. return true
  43. }
  44. }
  45. return false
  46. }
  47. func marshalToJsonString(value interface{}) (*string, error) {
  48. mBytes, err := json.Marshal(value)
  49. if err != nil {
  50. return nil, err
  51. }
  52. sBytes := string(mBytes)
  53. return &sBytes, nil
  54. }
  55. func isJsonNumber(what interface{}) bool {
  56. switch what.(type) {
  57. case json.Number:
  58. return true
  59. }
  60. return false
  61. }
  62. func checkJsonNumber(what interface{}) (isValidFloat64 bool, isValidInt64 bool, isValidInt32 bool) {
  63. jsonNumber := what.(json.Number)
  64. _, errFloat64 := jsonNumber.Float64()
  65. _, errInt64 := jsonNumber.Int64()
  66. isValidFloat64 = errFloat64 == nil
  67. isValidInt64 = errInt64 == nil
  68. _, errInt32 := strconv.ParseInt(jsonNumber.String(), 10, 32)
  69. isValidInt32 = isValidInt64 && errInt32 == nil
  70. return
  71. }
  72. // same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER
  73. const (
  74. max_json_float = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1
  75. min_json_float = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1
  76. )
  77. func isFloat64AnInteger(f float64) bool {
  78. if math.IsNaN(f) || math.IsInf(f, 0) || f < min_json_float || f > max_json_float {
  79. return false
  80. }
  81. return f == float64(int64(f)) || f == float64(uint64(f))
  82. }
  83. func mustBeInteger(what interface{}) *int {
  84. if isJsonNumber(what) {
  85. number := what.(json.Number)
  86. _, _, isValidInt32 := checkJsonNumber(number)
  87. if isValidInt32 {
  88. int64Value, err := number.Int64()
  89. if err != nil {
  90. return nil
  91. }
  92. int32Value := int(int64Value)
  93. return &int32Value
  94. } else {
  95. return nil
  96. }
  97. }
  98. return nil
  99. }
  100. func mustBeNumber(what interface{}) *float64 {
  101. if isJsonNumber(what) {
  102. number := what.(json.Number)
  103. float64Value, err := number.Float64()
  104. if err == nil {
  105. return &float64Value
  106. } else {
  107. return nil
  108. }
  109. }
  110. return nil
  111. }
  112. // formats a number so that it is displayed as the smallest string possible
  113. func resultErrorFormatJsonNumber(n json.Number) string {
  114. if int64Value, err := n.Int64(); err == nil {
  115. return fmt.Sprintf("%d", int64Value)
  116. }
  117. float64Value, _ := n.Float64()
  118. return fmt.Sprintf("%g", float64Value)
  119. }
  120. // formats a number so that it is displayed as the smallest string possible
  121. func resultErrorFormatNumber(n float64) string {
  122. if isFloat64AnInteger(n) {
  123. return fmt.Sprintf("%d", int64(n))
  124. }
  125. return fmt.Sprintf("%g", n)
  126. }
  127. func convertDocumentNode(val interface{}) interface{} {
  128. if lval, ok := val.([]interface{}); ok {
  129. res := []interface{}{}
  130. for _, v := range lval {
  131. res = append(res, convertDocumentNode(v))
  132. }
  133. return res
  134. }
  135. if mval, ok := val.(map[interface{}]interface{}); ok {
  136. res := map[string]interface{}{}
  137. for k, v := range mval {
  138. res[k.(string)] = convertDocumentNode(v)
  139. }
  140. return res
  141. }
  142. return val
  143. }