override.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. package common
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/tidwall/gjson"
  6. "github.com/tidwall/sjson"
  7. "strings"
  8. )
  9. type ConditionOperation struct {
  10. Path string `json:"path"` // JSON路径
  11. Mode string `json:"mode"` // full, prefix, suffix, contains
  12. Value string `json:"value"` // 匹配的值
  13. }
  14. type ParamOperation struct {
  15. Path string `json:"path"`
  16. Mode string `json:"mode"` // delete, set, move, prepend, append
  17. Value interface{} `json:"value"`
  18. KeepOrigin bool `json:"keep_origin"`
  19. From string `json:"from,omitempty"`
  20. To string `json:"to,omitempty"`
  21. Conditions []ConditionOperation `json:"conditions,omitempty"` // 条件列表
  22. Logic string `json:"logic,omitempty"` // AND, OR (默认OR)
  23. }
  24. func ApplyParamOverride(jsonData []byte, paramOverride map[string]interface{}) ([]byte, error) {
  25. if len(paramOverride) == 0 {
  26. return jsonData, nil
  27. }
  28. // 尝试断言为操作格式
  29. if operations, ok := tryParseOperations(paramOverride); ok {
  30. // 使用新方法
  31. result, err := applyOperations(string(jsonData), operations)
  32. if err != nil {
  33. // 新方法失败,回退到旧方法
  34. return applyOperationsLegacy(jsonData, paramOverride)
  35. }
  36. return []byte(result), nil
  37. }
  38. // 直接使用旧方法
  39. return applyOperationsLegacy(jsonData, paramOverride)
  40. }
  41. func tryParseOperations(paramOverride map[string]interface{}) ([]ParamOperation, bool) {
  42. // 检查是否包含 "operations" 字段
  43. if opsValue, exists := paramOverride["operations"]; exists {
  44. if opsSlice, ok := opsValue.([]interface{}); ok {
  45. var operations []ParamOperation
  46. for _, op := range opsSlice {
  47. if opMap, ok := op.(map[string]interface{}); ok {
  48. operation := ParamOperation{}
  49. // 断言必要字段
  50. if path, ok := opMap["path"].(string); ok {
  51. operation.Path = path
  52. }
  53. if mode, ok := opMap["mode"].(string); ok {
  54. operation.Mode = mode
  55. } else {
  56. return nil, false // mode 是必需的
  57. }
  58. // 可选字段
  59. if value, exists := opMap["value"]; exists {
  60. operation.Value = value
  61. }
  62. if keepOrigin, ok := opMap["keep_origin"].(bool); ok {
  63. operation.KeepOrigin = keepOrigin
  64. }
  65. if from, ok := opMap["from"].(string); ok {
  66. operation.From = from
  67. }
  68. if to, ok := opMap["to"].(string); ok {
  69. operation.To = to
  70. }
  71. if logic, ok := opMap["logic"].(string); ok {
  72. operation.Logic = logic
  73. } else {
  74. operation.Logic = "OR" // 默认为OR
  75. }
  76. // 解析条件
  77. if conditions, exists := opMap["conditions"]; exists {
  78. if condSlice, ok := conditions.([]interface{}); ok {
  79. for _, cond := range condSlice {
  80. if condMap, ok := cond.(map[string]interface{}); ok {
  81. condition := ConditionOperation{}
  82. if path, ok := condMap["path"].(string); ok {
  83. condition.Path = path
  84. }
  85. if mode, ok := condMap["mode"].(string); ok {
  86. condition.Mode = mode
  87. }
  88. if value, ok := condMap["value"].(string); ok {
  89. condition.Value = value
  90. }
  91. operation.Conditions = append(operation.Conditions, condition)
  92. }
  93. }
  94. }
  95. }
  96. operations = append(operations, operation)
  97. } else {
  98. return nil, false
  99. }
  100. }
  101. return operations, true
  102. }
  103. }
  104. return nil, false
  105. }
  106. func checkConditions(jsonStr string, conditions []ConditionOperation, logic string) bool {
  107. if len(conditions) == 0 {
  108. return true // 没有条件,直接通过
  109. }
  110. results := make([]bool, len(conditions))
  111. for i, condition := range conditions {
  112. results[i] = checkSingleCondition(jsonStr, condition)
  113. }
  114. if strings.ToUpper(logic) == "AND" {
  115. for _, result := range results {
  116. if !result {
  117. return false
  118. }
  119. }
  120. return true
  121. } else {
  122. for _, result := range results {
  123. if result {
  124. return true
  125. }
  126. }
  127. return false
  128. }
  129. }
  130. func checkSingleCondition(jsonStr string, condition ConditionOperation) bool {
  131. value := gjson.Get(jsonStr, condition.Path)
  132. if !value.Exists() {
  133. return false
  134. }
  135. valueStr := value.String()
  136. targetStr := condition.Value
  137. switch strings.ToLower(condition.Mode) {
  138. case "full":
  139. return valueStr == targetStr
  140. case "prefix":
  141. return strings.HasPrefix(valueStr, targetStr)
  142. case "suffix":
  143. return strings.HasSuffix(valueStr, targetStr)
  144. case "contains":
  145. return strings.Contains(valueStr, targetStr)
  146. default:
  147. return valueStr == targetStr // 默认精准匹配
  148. }
  149. }
  150. // applyOperationsLegacy 原参数覆盖方法
  151. func applyOperationsLegacy(jsonData []byte, paramOverride map[string]interface{}) ([]byte, error) {
  152. reqMap := make(map[string]interface{})
  153. err := json.Unmarshal(jsonData, &reqMap)
  154. if err != nil {
  155. return nil, err
  156. }
  157. for key, value := range paramOverride {
  158. reqMap[key] = value
  159. }
  160. return json.Marshal(reqMap)
  161. }
  162. func applyOperations(jsonStr string, operations []ParamOperation) (string, error) {
  163. result := jsonStr
  164. for _, op := range operations {
  165. // 检查条件是否满足
  166. if !checkConditions(result, op.Conditions, op.Logic) {
  167. continue // 条件不满足,跳过当前操作
  168. }
  169. var err error
  170. switch op.Mode {
  171. case "delete":
  172. result, err = sjson.Delete(result, op.Path)
  173. case "set":
  174. if op.KeepOrigin && gjson.Get(result, op.Path).Exists() {
  175. continue
  176. }
  177. result, err = sjson.Set(result, op.Path, op.Value)
  178. case "move":
  179. result, err = moveValue(result, op.From, op.To, op.KeepOrigin)
  180. case "prepend":
  181. result, err = modifyValue(result, op.Path, op.Value, op.KeepOrigin, true)
  182. case "append":
  183. result, err = modifyValue(result, op.Path, op.Value, op.KeepOrigin, false)
  184. default:
  185. return "", fmt.Errorf("unknown operation: %s", op.Mode)
  186. }
  187. if err != nil {
  188. return "", fmt.Errorf("operation %s failed: %v", op.Mode, err)
  189. }
  190. }
  191. return result, nil
  192. }
  193. func moveValue(jsonStr, fromPath, toPath string, keepOrigin bool) (string, error) {
  194. sourceValue := gjson.Get(jsonStr, fromPath)
  195. if !sourceValue.Exists() {
  196. return jsonStr, fmt.Errorf("source path does not exist: %s", fromPath)
  197. }
  198. if keepOrigin && gjson.Get(jsonStr, toPath).Exists() {
  199. return sjson.Delete(jsonStr, fromPath)
  200. }
  201. result, err := sjson.Set(jsonStr, toPath, sourceValue.Value())
  202. if err != nil {
  203. return "", err
  204. }
  205. return sjson.Delete(result, fromPath)
  206. }
  207. func modifyValue(jsonStr, path string, value interface{}, keepOrigin, isPrepend bool) (string, error) {
  208. current := gjson.Get(jsonStr, path)
  209. switch {
  210. case current.IsArray():
  211. return modifyArray(jsonStr, path, value, isPrepend)
  212. case current.Type == gjson.String:
  213. return modifyString(jsonStr, path, value, isPrepend)
  214. case current.Type == gjson.JSON:
  215. return mergeObjects(jsonStr, path, value, keepOrigin)
  216. }
  217. return jsonStr, fmt.Errorf("operation not supported for type: %v", current.Type)
  218. }
  219. func modifyArray(jsonStr, path string, value interface{}, isPrepend bool) (string, error) {
  220. current := gjson.Get(jsonStr, path)
  221. var newArray []interface{}
  222. // 添加新值
  223. addValue := func() {
  224. if arr, ok := value.([]interface{}); ok {
  225. newArray = append(newArray, arr...)
  226. } else {
  227. newArray = append(newArray, value)
  228. }
  229. }
  230. // 添加原值
  231. addOriginal := func() {
  232. current.ForEach(func(_, val gjson.Result) bool {
  233. newArray = append(newArray, val.Value())
  234. return true
  235. })
  236. }
  237. if isPrepend {
  238. addValue()
  239. addOriginal()
  240. } else {
  241. addOriginal()
  242. addValue()
  243. }
  244. return sjson.Set(jsonStr, path, newArray)
  245. }
  246. func modifyString(jsonStr, path string, value interface{}, isPrepend bool) (string, error) {
  247. current := gjson.Get(jsonStr, path)
  248. valueStr := fmt.Sprintf("%v", value)
  249. var newStr string
  250. if isPrepend {
  251. newStr = valueStr + current.String()
  252. } else {
  253. newStr = current.String() + valueStr
  254. }
  255. return sjson.Set(jsonStr, path, newStr)
  256. }
  257. func mergeObjects(jsonStr, path string, value interface{}, keepOrigin bool) (string, error) {
  258. current := gjson.Get(jsonStr, path)
  259. var currentMap, newMap map[string]interface{}
  260. // 解析当前值
  261. if err := json.Unmarshal([]byte(current.Raw), &currentMap); err != nil {
  262. return "", err
  263. }
  264. // 解析新值
  265. switch v := value.(type) {
  266. case map[string]interface{}:
  267. newMap = v
  268. default:
  269. jsonBytes, _ := json.Marshal(v)
  270. if err := json.Unmarshal(jsonBytes, &newMap); err != nil {
  271. return "", err
  272. }
  273. }
  274. // 合并
  275. result := make(map[string]interface{})
  276. for k, v := range currentMap {
  277. result[k] = v
  278. }
  279. for k, v := range newMap {
  280. if !keepOrigin || result[k] == nil {
  281. result[k] = v
  282. }
  283. }
  284. return sjson.Set(jsonStr, path, result)
  285. }