gjson.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  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. "reflect"
  10. "strconv"
  11. "strings"
  12. "github.com/gogf/gf/v2/errors/gcode"
  13. "github.com/gogf/gf/v2/errors/gerror"
  14. "github.com/gogf/gf/v2/internal/reflection"
  15. "github.com/gogf/gf/v2/internal/rwmutex"
  16. "github.com/gogf/gf/v2/internal/utils"
  17. "github.com/gogf/gf/v2/text/gstr"
  18. "github.com/gogf/gf/v2/util/gconv"
  19. )
  20. type ContentType string
  21. const (
  22. ContentTypeJson ContentType = `json`
  23. ContentTypeJs ContentType = `js`
  24. ContentTypeXml ContentType = `xml`
  25. ContentTypeIni ContentType = `ini`
  26. ContentTypeYaml ContentType = `yaml`
  27. ContentTypeYml ContentType = `yml`
  28. ContentTypeToml ContentType = `toml`
  29. ContentTypeProperties ContentType = `properties`
  30. )
  31. const (
  32. defaultSplitChar = '.' // Separator char for hierarchical data access.
  33. )
  34. // Json is the customized JSON struct.
  35. type Json struct {
  36. mu rwmutex.RWMutex
  37. p *interface{} // Pointer for hierarchical data access, it's the root of data in default.
  38. c byte // Char separator('.' in default).
  39. vc bool // Violence Check(false in default), which is used to access data when the hierarchical data key contains separator char.
  40. }
  41. // Options for Json object creating/loading.
  42. type Options struct {
  43. Safe bool // Mark this object is for in concurrent-safe usage. This is especially for Json object creating.
  44. Tags string // Custom priority tags for decoding, eg: "json,yaml,MyTag". This is especially for struct parsing into Json object.
  45. Type ContentType // Type specifies the data content type, eg: json, xml, yaml, toml, ini.
  46. StrNumber bool // StrNumber causes the Decoder to unmarshal a number into an interface{} as a string instead of as a float64.
  47. }
  48. // iInterfaces is used for type assert api for Interfaces().
  49. type iInterfaces interface {
  50. Interfaces() []interface{}
  51. }
  52. // iMapStrAny is the interface support for converting struct parameter to map.
  53. type iMapStrAny interface {
  54. MapStrAny() map[string]interface{}
  55. }
  56. // iVal is the interface for underlying interface{} retrieving.
  57. type iVal interface {
  58. Val() interface{}
  59. }
  60. // setValue sets `value` to `j` by `pattern`.
  61. // Note:
  62. // 1. If value is nil and removed is true, means deleting this value;
  63. // 2. It's quite complicated in hierarchical data search, node creating and data assignment;
  64. func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
  65. var (
  66. err error
  67. array = strings.Split(pattern, string(j.c))
  68. length = len(array)
  69. )
  70. if value, err = j.convertValue(value); err != nil {
  71. return err
  72. }
  73. // Initialization checks.
  74. if *j.p == nil {
  75. if gstr.IsNumeric(array[0]) {
  76. *j.p = make([]interface{}, 0)
  77. } else {
  78. *j.p = make(map[string]interface{})
  79. }
  80. }
  81. var (
  82. pparent *interface{} = nil // Parent pointer.
  83. pointer *interface{} = j.p // Current pointer.
  84. )
  85. j.mu.Lock()
  86. defer j.mu.Unlock()
  87. for i := 0; i < length; i++ {
  88. switch (*pointer).(type) {
  89. case map[string]interface{}:
  90. if i == length-1 {
  91. if removed && value == nil {
  92. // Delete item from map.
  93. delete((*pointer).(map[string]interface{}), array[i])
  94. } else {
  95. if (*pointer).(map[string]interface{}) == nil {
  96. *pointer = map[string]interface{}{}
  97. }
  98. (*pointer).(map[string]interface{})[array[i]] = value
  99. }
  100. } else {
  101. // If the key does not exit in the map.
  102. if v, ok := (*pointer).(map[string]interface{})[array[i]]; !ok {
  103. if removed && value == nil {
  104. goto done
  105. }
  106. // Creating new node.
  107. if gstr.IsNumeric(array[i+1]) {
  108. // Creating array node.
  109. n, _ := strconv.Atoi(array[i+1])
  110. var v interface{} = make([]interface{}, n+1)
  111. pparent = j.setPointerWithValue(pointer, array[i], v)
  112. pointer = &v
  113. } else {
  114. // Creating map node.
  115. var v interface{} = make(map[string]interface{})
  116. pparent = j.setPointerWithValue(pointer, array[i], v)
  117. pointer = &v
  118. }
  119. } else {
  120. pparent = pointer
  121. pointer = &v
  122. }
  123. }
  124. case []interface{}:
  125. // A string key.
  126. if !gstr.IsNumeric(array[i]) {
  127. if i == length-1 {
  128. *pointer = map[string]interface{}{array[i]: value}
  129. } else {
  130. var v interface{} = make(map[string]interface{})
  131. *pointer = v
  132. pparent = pointer
  133. pointer = &v
  134. }
  135. continue
  136. }
  137. // Numeric index.
  138. valueNum, err := strconv.Atoi(array[i])
  139. if err != nil {
  140. err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `strconv.Atoi failed for string "%s"`, array[i])
  141. return err
  142. }
  143. if i == length-1 {
  144. // Leaf node.
  145. if len((*pointer).([]interface{})) > valueNum {
  146. if removed && value == nil {
  147. // Deleting element.
  148. if pparent == nil {
  149. *pointer = append((*pointer).([]interface{})[:valueNum], (*pointer).([]interface{})[valueNum+1:]...)
  150. } else {
  151. j.setPointerWithValue(pparent, array[i-1], append((*pointer).([]interface{})[:valueNum], (*pointer).([]interface{})[valueNum+1:]...))
  152. }
  153. } else {
  154. (*pointer).([]interface{})[valueNum] = value
  155. }
  156. } else {
  157. if removed && value == nil {
  158. goto done
  159. }
  160. if pparent == nil {
  161. // It is the root node.
  162. j.setPointerWithValue(pointer, array[i], value)
  163. } else {
  164. // It is not the root node.
  165. s := make([]interface{}, valueNum+1)
  166. copy(s, (*pointer).([]interface{}))
  167. s[valueNum] = value
  168. j.setPointerWithValue(pparent, array[i-1], s)
  169. }
  170. }
  171. } else {
  172. // Branch node.
  173. if gstr.IsNumeric(array[i+1]) {
  174. n, _ := strconv.Atoi(array[i+1])
  175. pSlice := (*pointer).([]interface{})
  176. if len(pSlice) > valueNum {
  177. item := pSlice[valueNum]
  178. if s, ok := item.([]interface{}); ok {
  179. for i := 0; i < n-len(s); i++ {
  180. s = append(s, nil)
  181. }
  182. pparent = pointer
  183. pointer = &pSlice[valueNum]
  184. } else {
  185. if removed && value == nil {
  186. goto done
  187. }
  188. var v interface{} = make([]interface{}, n+1)
  189. pparent = j.setPointerWithValue(pointer, array[i], v)
  190. pointer = &v
  191. }
  192. } else {
  193. if removed && value == nil {
  194. goto done
  195. }
  196. var v interface{} = make([]interface{}, n+1)
  197. pparent = j.setPointerWithValue(pointer, array[i], v)
  198. pointer = &v
  199. }
  200. } else {
  201. pSlice := (*pointer).([]interface{})
  202. if len(pSlice) > valueNum {
  203. pparent = pointer
  204. pointer = &(*pointer).([]interface{})[valueNum]
  205. } else {
  206. s := make([]interface{}, valueNum+1)
  207. copy(s, pSlice)
  208. s[valueNum] = make(map[string]interface{})
  209. if pparent != nil {
  210. // i > 0
  211. j.setPointerWithValue(pparent, array[i-1], s)
  212. pparent = pointer
  213. pointer = &s[valueNum]
  214. } else {
  215. // i = 0
  216. var v interface{} = s
  217. *pointer = v
  218. pparent = pointer
  219. pointer = &s[valueNum]
  220. }
  221. }
  222. }
  223. }
  224. // If the variable pointed to by the `pointer` is not of a reference type,
  225. // then it modifies the variable via its the parent, ie: pparent.
  226. default:
  227. if removed && value == nil {
  228. goto done
  229. }
  230. if gstr.IsNumeric(array[i]) {
  231. n, _ := strconv.Atoi(array[i])
  232. s := make([]interface{}, n+1)
  233. if i == length-1 {
  234. s[n] = value
  235. }
  236. if pparent != nil {
  237. pparent = j.setPointerWithValue(pparent, array[i-1], s)
  238. } else {
  239. *pointer = s
  240. pparent = pointer
  241. }
  242. } else {
  243. var v1, v2 interface{}
  244. if i == length-1 {
  245. v1 = map[string]interface{}{
  246. array[i]: value,
  247. }
  248. } else {
  249. v1 = map[string]interface{}{
  250. array[i]: nil,
  251. }
  252. }
  253. if pparent != nil {
  254. pparent = j.setPointerWithValue(pparent, array[i-1], v1)
  255. } else {
  256. *pointer = v1
  257. pparent = pointer
  258. }
  259. v2 = v1.(map[string]interface{})[array[i]]
  260. pointer = &v2
  261. }
  262. }
  263. }
  264. done:
  265. return nil
  266. }
  267. // convertValue converts `value` to map[string]interface{} or []interface{},
  268. // which can be supported for hierarchical data access.
  269. func (j *Json) convertValue(value interface{}) (convertedValue interface{}, err error) {
  270. if value == nil {
  271. return
  272. }
  273. switch value.(type) {
  274. case map[string]interface{}:
  275. return value, nil
  276. case []interface{}:
  277. return value, nil
  278. default:
  279. var (
  280. reflectInfo = reflection.OriginValueAndKind(value)
  281. )
  282. switch reflectInfo.OriginKind {
  283. case reflect.Array:
  284. return gconv.Interfaces(value), nil
  285. case reflect.Slice:
  286. return gconv.Interfaces(value), nil
  287. case reflect.Map:
  288. return gconv.Map(value), nil
  289. case reflect.Struct:
  290. if v, ok := value.(iMapStrAny); ok {
  291. convertedValue = v.MapStrAny()
  292. }
  293. if utils.IsNil(convertedValue) {
  294. if v, ok := value.(iInterfaces); ok {
  295. convertedValue = v.Interfaces()
  296. }
  297. }
  298. if utils.IsNil(convertedValue) {
  299. convertedValue = gconv.Map(value)
  300. }
  301. if utils.IsNil(convertedValue) {
  302. err = gerror.NewCodef(gcode.CodeInvalidParameter, `unsupported value type "%s"`, reflect.TypeOf(value))
  303. }
  304. return
  305. default:
  306. return value, nil
  307. }
  308. }
  309. }
  310. // setPointerWithValue sets `key`:`value` to `pointer`, the `key` may be a map key or slice index.
  311. // It returns the pointer to the new value set.
  312. func (j *Json) setPointerWithValue(pointer *interface{}, key string, value interface{}) *interface{} {
  313. switch (*pointer).(type) {
  314. case map[string]interface{}:
  315. (*pointer).(map[string]interface{})[key] = value
  316. return &value
  317. case []interface{}:
  318. n, _ := strconv.Atoi(key)
  319. if len((*pointer).([]interface{})) > n {
  320. (*pointer).([]interface{})[n] = value
  321. return &(*pointer).([]interface{})[n]
  322. } else {
  323. s := make([]interface{}, n+1)
  324. copy(s, (*pointer).([]interface{}))
  325. s[n] = value
  326. *pointer = s
  327. return &s[n]
  328. }
  329. default:
  330. *pointer = value
  331. }
  332. return pointer
  333. }
  334. // getPointerByPattern returns a pointer to the value by specified `pattern`.
  335. func (j *Json) getPointerByPattern(pattern string) *interface{} {
  336. if j.p == nil {
  337. return nil
  338. }
  339. if j.vc {
  340. return j.getPointerByPatternWithViolenceCheck(pattern)
  341. } else {
  342. return j.getPointerByPatternWithoutViolenceCheck(pattern)
  343. }
  344. }
  345. // getPointerByPatternWithViolenceCheck returns a pointer to the value of specified `pattern` with violence check.
  346. func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{} {
  347. if !j.vc {
  348. return j.getPointerByPatternWithoutViolenceCheck(pattern)
  349. }
  350. // It returns nil if pattern is empty.
  351. if pattern == "" {
  352. return nil
  353. }
  354. // It returns all if pattern is ".".
  355. if pattern == "." {
  356. return j.p
  357. }
  358. var (
  359. index = len(pattern)
  360. start = 0
  361. length = 0
  362. pointer = j.p
  363. )
  364. if index == 0 {
  365. return pointer
  366. }
  367. for {
  368. if r := j.checkPatternByPointer(pattern[start:index], pointer); r != nil {
  369. if length += index - start; start > 0 {
  370. length += 1
  371. }
  372. start = index + 1
  373. index = len(pattern)
  374. if length == len(pattern) {
  375. return r
  376. } else {
  377. pointer = r
  378. }
  379. } else {
  380. // Get the position for next separator char.
  381. index = strings.LastIndexByte(pattern[start:index], j.c)
  382. if index != -1 && length > 0 {
  383. index += length + 1
  384. }
  385. }
  386. if start >= index {
  387. break
  388. }
  389. }
  390. return nil
  391. }
  392. // getPointerByPatternWithoutViolenceCheck returns a pointer to the value of specified `pattern`, with no violence check.
  393. func (j *Json) getPointerByPatternWithoutViolenceCheck(pattern string) *interface{} {
  394. if j.vc {
  395. return j.getPointerByPatternWithViolenceCheck(pattern)
  396. }
  397. // It returns nil if pattern is empty.
  398. if pattern == "" {
  399. return nil
  400. }
  401. // It returns all if pattern is ".".
  402. if pattern == "." {
  403. return j.p
  404. }
  405. pointer := j.p
  406. if len(pattern) == 0 {
  407. return pointer
  408. }
  409. array := strings.Split(pattern, string(j.c))
  410. for k, v := range array {
  411. if r := j.checkPatternByPointer(v, pointer); r != nil {
  412. if k == len(array)-1 {
  413. return r
  414. } else {
  415. pointer = r
  416. }
  417. } else {
  418. break
  419. }
  420. }
  421. return nil
  422. }
  423. // checkPatternByPointer checks whether there's value by `key` in specified `pointer`.
  424. // It returns a pointer to the value.
  425. func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interface{} {
  426. switch (*pointer).(type) {
  427. case map[string]interface{}:
  428. if v, ok := (*pointer).(map[string]interface{})[key]; ok {
  429. return &v
  430. }
  431. case []interface{}:
  432. if gstr.IsNumeric(key) {
  433. n, err := strconv.Atoi(key)
  434. if err == nil && len((*pointer).([]interface{})) > n {
  435. return &(*pointer).([]interface{})[n]
  436. }
  437. }
  438. }
  439. return nil
  440. }