gjson.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. // Package gjson provides convenient API for JSON/XML/INI/YAML/TOML data handling.
  7. package gjson
  8. import (
  9. "github.com/gogf/gf/internal/utils"
  10. "reflect"
  11. "strconv"
  12. "strings"
  13. "github.com/gogf/gf/internal/rwmutex"
  14. "github.com/gogf/gf/text/gstr"
  15. "github.com/gogf/gf/util/gconv"
  16. )
  17. const (
  18. // Separator char for hierarchical data access.
  19. defaultSplitChar = '.'
  20. )
  21. // Json is the customized JSON struct.
  22. type Json struct {
  23. mu *rwmutex.RWMutex
  24. p *interface{} // Pointer for hierarchical data access, it's the root of data in default.
  25. c byte // Char separator('.' in default).
  26. vc bool // Violence Check(false in default), which is used to access data when the hierarchical data key contains separator char.
  27. }
  28. // Options for Json object creating.
  29. type Options struct {
  30. Safe bool // Mark this object is for in concurrent-safe usage.
  31. Tags string // Custom priority tags for decoding.
  32. StrNumber bool // StrNumber causes the Decoder to unmarshal a number into an interface{} as a string instead of as a float64.
  33. }
  34. // apiInterface is used for type assert api for Interface().
  35. type apiInterface interface {
  36. Interface() interface{}
  37. }
  38. // setValue sets <value> to <j> by <pattern>.
  39. // Note:
  40. // 1. If value is nil and removed is true, means deleting this value;
  41. // 2. It's quite complicated in hierarchical data search, node creating and data assignment;
  42. func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
  43. if value != nil {
  44. if utils.IsStruct(value) {
  45. if v, ok := value.(apiInterface); ok {
  46. value = v.Interface()
  47. }
  48. }
  49. }
  50. array := strings.Split(pattern, string(j.c))
  51. length := len(array)
  52. value = j.convertValue(value)
  53. // Initialization checks.
  54. if *j.p == nil {
  55. if gstr.IsNumeric(array[0]) {
  56. *j.p = make([]interface{}, 0)
  57. } else {
  58. *j.p = make(map[string]interface{})
  59. }
  60. }
  61. var pparent *interface{} = nil // Parent pointer.
  62. var pointer *interface{} = j.p // Current pointer.
  63. j.mu.Lock()
  64. defer j.mu.Unlock()
  65. for i := 0; i < length; i++ {
  66. switch (*pointer).(type) {
  67. case map[string]interface{}:
  68. if i == length-1 {
  69. if removed && value == nil {
  70. // Delete item from map.
  71. delete((*pointer).(map[string]interface{}), array[i])
  72. } else {
  73. (*pointer).(map[string]interface{})[array[i]] = value
  74. }
  75. } else {
  76. // If the key does not exit in the map.
  77. if v, ok := (*pointer).(map[string]interface{})[array[i]]; !ok {
  78. if removed && value == nil {
  79. goto done
  80. }
  81. // Creating new node.
  82. if gstr.IsNumeric(array[i+1]) {
  83. // Creating array node.
  84. n, _ := strconv.Atoi(array[i+1])
  85. var v interface{} = make([]interface{}, n+1)
  86. pparent = j.setPointerWithValue(pointer, array[i], v)
  87. pointer = &v
  88. } else {
  89. // Creating map node.
  90. var v interface{} = make(map[string]interface{})
  91. pparent = j.setPointerWithValue(pointer, array[i], v)
  92. pointer = &v
  93. }
  94. } else {
  95. pparent = pointer
  96. pointer = &v
  97. }
  98. }
  99. case []interface{}:
  100. // A string key.
  101. if !gstr.IsNumeric(array[i]) {
  102. if i == length-1 {
  103. *pointer = map[string]interface{}{array[i]: value}
  104. } else {
  105. var v interface{} = make(map[string]interface{})
  106. *pointer = v
  107. pparent = pointer
  108. pointer = &v
  109. }
  110. continue
  111. }
  112. // Numeric index.
  113. valueNum, err := strconv.Atoi(array[i])
  114. if err != nil {
  115. return err
  116. }
  117. if i == length-1 {
  118. // Leaf node.
  119. if len((*pointer).([]interface{})) > valueNum {
  120. if removed && value == nil {
  121. // Deleting element.
  122. if pparent == nil {
  123. *pointer = append((*pointer).([]interface{})[:valueNum], (*pointer).([]interface{})[valueNum+1:]...)
  124. } else {
  125. j.setPointerWithValue(pparent, array[i-1], append((*pointer).([]interface{})[:valueNum], (*pointer).([]interface{})[valueNum+1:]...))
  126. }
  127. } else {
  128. (*pointer).([]interface{})[valueNum] = value
  129. }
  130. } else {
  131. if removed && value == nil {
  132. goto done
  133. }
  134. if pparent == nil {
  135. // It is the root node.
  136. j.setPointerWithValue(pointer, array[i], value)
  137. } else {
  138. // It is not the root node.
  139. s := make([]interface{}, valueNum+1)
  140. copy(s, (*pointer).([]interface{}))
  141. s[valueNum] = value
  142. j.setPointerWithValue(pparent, array[i-1], s)
  143. }
  144. }
  145. } else {
  146. // Branch node.
  147. if gstr.IsNumeric(array[i+1]) {
  148. n, _ := strconv.Atoi(array[i+1])
  149. pSlice := (*pointer).([]interface{})
  150. if len(pSlice) > valueNum {
  151. item := pSlice[valueNum]
  152. if s, ok := item.([]interface{}); ok {
  153. for i := 0; i < n-len(s); i++ {
  154. s = append(s, nil)
  155. }
  156. pparent = pointer
  157. pointer = &pSlice[valueNum]
  158. } else {
  159. if removed && value == nil {
  160. goto done
  161. }
  162. var v interface{} = make([]interface{}, n+1)
  163. pparent = j.setPointerWithValue(pointer, array[i], v)
  164. pointer = &v
  165. }
  166. } else {
  167. if removed && value == nil {
  168. goto done
  169. }
  170. var v interface{} = make([]interface{}, n+1)
  171. pparent = j.setPointerWithValue(pointer, array[i], v)
  172. pointer = &v
  173. }
  174. } else {
  175. pSlice := (*pointer).([]interface{})
  176. if len(pSlice) > valueNum {
  177. pparent = pointer
  178. pointer = &(*pointer).([]interface{})[valueNum]
  179. } else {
  180. s := make([]interface{}, valueNum+1)
  181. copy(s, pSlice)
  182. s[valueNum] = make(map[string]interface{})
  183. if pparent != nil {
  184. // i > 0
  185. j.setPointerWithValue(pparent, array[i-1], s)
  186. pparent = pointer
  187. pointer = &s[valueNum]
  188. } else {
  189. // i = 0
  190. var v interface{} = s
  191. *pointer = v
  192. pparent = pointer
  193. pointer = &s[valueNum]
  194. }
  195. }
  196. }
  197. }
  198. // If the variable pointed to by the <pointer> is not of a reference type,
  199. // then it modifies the variable via its the parent, ie: pparent.
  200. default:
  201. if removed && value == nil {
  202. goto done
  203. }
  204. if gstr.IsNumeric(array[i]) {
  205. n, _ := strconv.Atoi(array[i])
  206. s := make([]interface{}, n+1)
  207. if i == length-1 {
  208. s[n] = value
  209. }
  210. if pparent != nil {
  211. pparent = j.setPointerWithValue(pparent, array[i-1], s)
  212. } else {
  213. *pointer = s
  214. pparent = pointer
  215. }
  216. } else {
  217. var v1, v2 interface{}
  218. if i == length-1 {
  219. v1 = map[string]interface{}{
  220. array[i]: value,
  221. }
  222. } else {
  223. v1 = map[string]interface{}{
  224. array[i]: nil,
  225. }
  226. }
  227. if pparent != nil {
  228. pparent = j.setPointerWithValue(pparent, array[i-1], v1)
  229. } else {
  230. *pointer = v1
  231. pparent = pointer
  232. }
  233. v2 = v1.(map[string]interface{})[array[i]]
  234. pointer = &v2
  235. }
  236. }
  237. }
  238. done:
  239. return nil
  240. }
  241. // convertValue converts <value> to map[string]interface{} or []interface{},
  242. // which can be supported for hierarchical data access.
  243. func (j *Json) convertValue(value interface{}) interface{} {
  244. switch value.(type) {
  245. case map[string]interface{}:
  246. return value
  247. case []interface{}:
  248. return value
  249. default:
  250. rv := reflect.ValueOf(value)
  251. kind := rv.Kind()
  252. if kind == reflect.Ptr {
  253. rv = rv.Elem()
  254. kind = rv.Kind()
  255. }
  256. switch kind {
  257. case reflect.Array:
  258. return gconv.Interfaces(value)
  259. case reflect.Slice:
  260. return gconv.Interfaces(value)
  261. case reflect.Map:
  262. return gconv.Map(value)
  263. case reflect.Struct:
  264. return gconv.Map(value)
  265. default:
  266. // Use json decode/encode at last.
  267. b, _ := Encode(value)
  268. v, _ := Decode(b)
  269. return v
  270. }
  271. }
  272. }
  273. // setPointerWithValue sets <key>:<value> to <pointer>, the <key> may be a map key or slice index.
  274. // It returns the pointer to the new value set.
  275. func (j *Json) setPointerWithValue(pointer *interface{}, key string, value interface{}) *interface{} {
  276. switch (*pointer).(type) {
  277. case map[string]interface{}:
  278. (*pointer).(map[string]interface{})[key] = value
  279. return &value
  280. case []interface{}:
  281. n, _ := strconv.Atoi(key)
  282. if len((*pointer).([]interface{})) > n {
  283. (*pointer).([]interface{})[n] = value
  284. return &(*pointer).([]interface{})[n]
  285. } else {
  286. s := make([]interface{}, n+1)
  287. copy(s, (*pointer).([]interface{}))
  288. s[n] = value
  289. *pointer = s
  290. return &s[n]
  291. }
  292. default:
  293. *pointer = value
  294. }
  295. return pointer
  296. }
  297. // getPointerByPattern returns a pointer to the value by specified <pattern>.
  298. func (j *Json) getPointerByPattern(pattern string) *interface{} {
  299. if j.vc {
  300. return j.getPointerByPatternWithViolenceCheck(pattern)
  301. } else {
  302. return j.getPointerByPatternWithoutViolenceCheck(pattern)
  303. }
  304. }
  305. // getPointerByPatternWithViolenceCheck returns a pointer to the value of specified <pattern> with violence check.
  306. func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{} {
  307. if !j.vc {
  308. return j.getPointerByPatternWithoutViolenceCheck(pattern)
  309. }
  310. index := len(pattern)
  311. start := 0
  312. length := 0
  313. pointer := j.p
  314. if index == 0 {
  315. return pointer
  316. }
  317. for {
  318. if r := j.checkPatternByPointer(pattern[start:index], pointer); r != nil {
  319. length += index - start
  320. if start > 0 {
  321. length += 1
  322. }
  323. start = index + 1
  324. index = len(pattern)
  325. if length == len(pattern) {
  326. return r
  327. } else {
  328. pointer = r
  329. }
  330. } else {
  331. // Get the position for next separator char.
  332. index = strings.LastIndexByte(pattern[start:index], j.c)
  333. if index != -1 && length > 0 {
  334. index += length + 1
  335. }
  336. }
  337. if start >= index {
  338. break
  339. }
  340. }
  341. return nil
  342. }
  343. // getPointerByPatternWithoutViolenceCheck returns a pointer to the value of specified <pattern>, with no violence check.
  344. func (j *Json) getPointerByPatternWithoutViolenceCheck(pattern string) *interface{} {
  345. if j.vc {
  346. return j.getPointerByPatternWithViolenceCheck(pattern)
  347. }
  348. pointer := j.p
  349. if len(pattern) == 0 {
  350. return pointer
  351. }
  352. array := strings.Split(pattern, string(j.c))
  353. for k, v := range array {
  354. if r := j.checkPatternByPointer(v, pointer); r != nil {
  355. if k == len(array)-1 {
  356. return r
  357. } else {
  358. pointer = r
  359. }
  360. } else {
  361. break
  362. }
  363. }
  364. return nil
  365. }
  366. // checkPatternByPointer checks whether there's value by <key> in specified <pointer>.
  367. // It returns a pointer to the value.
  368. func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interface{} {
  369. switch (*pointer).(type) {
  370. case map[string]interface{}:
  371. if v, ok := (*pointer).(map[string]interface{})[key]; ok {
  372. return &v
  373. }
  374. case []interface{}:
  375. if gstr.IsNumeric(key) {
  376. n, err := strconv.Atoi(key)
  377. if err == nil && len((*pointer).([]interface{})) > n {
  378. return &(*pointer).([]interface{})[n]
  379. }
  380. }
  381. }
  382. return nil
  383. }