gstr_parse.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 gstr
  7. import (
  8. "net/url"
  9. "strings"
  10. "github.com/gogf/gf/v2/errors/gcode"
  11. "github.com/gogf/gf/v2/errors/gerror"
  12. )
  13. // Parse parses the string into map[string]interface{}.
  14. //
  15. // v1=m&v2=n -> map[v1:m v2:n]
  16. // v[a]=m&v[b]=n -> map[v:map[a:m b:n]]
  17. // v[a][a]=m&v[a][b]=n -> map[v:map[a:map[a:m b:n]]]
  18. // v[]=m&v[]=n -> map[v:[m n]]
  19. // v[a][]=m&v[a][]=n -> map[v:map[a:[m n]]]
  20. // v[][]=m&v[][]=n -> map[v:[map[]]] // Currently does not support nested slice.
  21. // v=m&v[a]=n -> error
  22. // a .[[b=c -> map[a___[b:c]
  23. func Parse(s string) (result map[string]interface{}, err error) {
  24. if s == "" {
  25. return nil, nil
  26. }
  27. result = make(map[string]interface{})
  28. parts := strings.Split(s, "&")
  29. for _, part := range parts {
  30. pos := strings.Index(part, "=")
  31. if pos <= 0 {
  32. continue
  33. }
  34. key, err := url.QueryUnescape(part[:pos])
  35. if err != nil {
  36. err = gerror.Wrapf(err, `url.QueryUnescape failed for string "%s"`, part[:pos])
  37. return nil, err
  38. }
  39. for len(key) > 0 && key[0] == ' ' {
  40. key = key[1:]
  41. }
  42. if key == "" || key[0] == '[' {
  43. continue
  44. }
  45. value, err := url.QueryUnescape(part[pos+1:])
  46. if err != nil {
  47. err = gerror.Wrapf(err, `url.QueryUnescape failed for string "%s"`, part[pos+1:])
  48. return nil, err
  49. }
  50. // split into multiple keys
  51. var keys []string
  52. left := 0
  53. for i, k := range key {
  54. if k == '[' && left == 0 {
  55. left = i
  56. } else if k == ']' {
  57. if left > 0 {
  58. if len(keys) == 0 {
  59. keys = append(keys, key[:left])
  60. }
  61. keys = append(keys, key[left+1:i])
  62. left = 0
  63. if i+1 < len(key) && key[i+1] != '[' {
  64. break
  65. }
  66. }
  67. }
  68. }
  69. if len(keys) == 0 {
  70. keys = append(keys, key)
  71. }
  72. // first key
  73. first := ""
  74. for i, chr := range keys[0] {
  75. if chr == ' ' || chr == '.' || chr == '[' {
  76. first += "_"
  77. } else {
  78. first += string(chr)
  79. }
  80. if chr == '[' {
  81. first += keys[0][i+1:]
  82. break
  83. }
  84. }
  85. keys[0] = first
  86. // build nested map
  87. if err = build(result, keys, value); err != nil {
  88. return nil, err
  89. }
  90. }
  91. return result, nil
  92. }
  93. // build nested map.
  94. func build(result map[string]interface{}, keys []string, value interface{}) error {
  95. var (
  96. length = len(keys)
  97. key = strings.Trim(keys[0], "'\"")
  98. )
  99. if length == 1 {
  100. result[key] = value
  101. return nil
  102. }
  103. // The end is slice. like f[], f[a][]
  104. if keys[1] == "" && length == 2 {
  105. // TODO nested slice
  106. if key == "" {
  107. return nil
  108. }
  109. val, ok := result[key]
  110. if !ok {
  111. result[key] = []interface{}{value}
  112. return nil
  113. }
  114. children, ok := val.([]interface{})
  115. if !ok {
  116. return gerror.NewCodef(
  117. gcode.CodeInvalidParameter,
  118. "expected type '[]interface{}' for key '%s', but got '%T'",
  119. key, val,
  120. )
  121. }
  122. result[key] = append(children, value)
  123. return nil
  124. }
  125. // The end is slice + map. like v[][a]
  126. if keys[1] == "" && length > 2 && keys[2] != "" {
  127. val, ok := result[key]
  128. if !ok {
  129. result[key] = []interface{}{}
  130. val = result[key]
  131. }
  132. children, ok := val.([]interface{})
  133. if !ok {
  134. return gerror.NewCodef(
  135. gcode.CodeInvalidParameter,
  136. "expected type '[]interface{}' for key '%s', but got '%T'",
  137. key, val,
  138. )
  139. }
  140. if l := len(children); l > 0 {
  141. if child, ok := children[l-1].(map[string]interface{}); ok {
  142. if _, ok := child[keys[2]]; !ok {
  143. _ = build(child, keys[2:], value)
  144. return nil
  145. }
  146. }
  147. }
  148. child := map[string]interface{}{}
  149. _ = build(child, keys[2:], value)
  150. result[key] = append(children, child)
  151. return nil
  152. }
  153. // map, like v[a], v[a][b]
  154. val, ok := result[key]
  155. if !ok {
  156. result[key] = map[string]interface{}{}
  157. val = result[key]
  158. }
  159. children, ok := val.(map[string]interface{})
  160. if !ok {
  161. return gerror.NewCodef(
  162. gcode.CodeInvalidParameter,
  163. "expected type 'map[string]interface{}' for key '%s', but got '%T'",
  164. key, val,
  165. )
  166. }
  167. if err := build(children, keys[1:], value); err != nil {
  168. return err
  169. }
  170. return nil
  171. }