gjson.go 10.0 KB

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