override.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. package common
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. "github.com/tidwall/gjson"
  9. "github.com/tidwall/sjson"
  10. )
  11. type ConditionOperation struct {
  12. Path string `json:"path"` // JSON路径
  13. Mode string `json:"mode"` // full, prefix, suffix, contains, gt, gte, lt, lte
  14. Value interface{} `json:"value"` // 匹配的值
  15. Invert bool `json:"invert"` // 反选功能,true表示取反结果
  16. PassMissingKey bool `json:"pass_missing_key"` // 未获取到json key时的行为
  17. }
  18. type ParamOperation struct {
  19. Path string `json:"path"`
  20. Mode string `json:"mode"` // delete, set, move, prepend, append
  21. Value interface{} `json:"value"`
  22. KeepOrigin bool `json:"keep_origin"`
  23. From string `json:"from,omitempty"`
  24. To string `json:"to,omitempty"`
  25. Conditions []ConditionOperation `json:"conditions,omitempty"` // 条件列表
  26. Logic string `json:"logic,omitempty"` // AND, OR (默认OR)
  27. }
  28. func ApplyParamOverride(jsonData []byte, paramOverride map[string]interface{}) ([]byte, error) {
  29. if len(paramOverride) == 0 {
  30. return jsonData, nil
  31. }
  32. // 尝试断言为操作格式
  33. if operations, ok := tryParseOperations(paramOverride); ok {
  34. // 使用新方法
  35. result, err := applyOperations(string(jsonData), operations)
  36. return []byte(result), err
  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"]; ok {
  89. condition.Value = value
  90. }
  91. if invert, ok := condMap["invert"].(bool); ok {
  92. condition.Invert = invert
  93. }
  94. if passMissingKey, ok := condMap["pass_missing_key"].(bool); ok {
  95. condition.PassMissingKey = passMissingKey
  96. }
  97. operation.Conditions = append(operation.Conditions, condition)
  98. }
  99. }
  100. }
  101. }
  102. operations = append(operations, operation)
  103. } else {
  104. return nil, false
  105. }
  106. }
  107. return operations, true
  108. }
  109. }
  110. return nil, false
  111. }
  112. func checkConditions(jsonStr string, conditions []ConditionOperation, logic string) (bool, error) {
  113. if len(conditions) == 0 {
  114. return true, nil // 没有条件,直接通过
  115. }
  116. results := make([]bool, len(conditions))
  117. for i, condition := range conditions {
  118. result, err := checkSingleCondition(jsonStr, condition)
  119. if err != nil {
  120. return false, err
  121. }
  122. results[i] = result
  123. }
  124. if strings.ToUpper(logic) == "AND" {
  125. for _, result := range results {
  126. if !result {
  127. return false, nil
  128. }
  129. }
  130. return true, nil
  131. } else {
  132. for _, result := range results {
  133. if result {
  134. return true, nil
  135. }
  136. }
  137. return false, nil
  138. }
  139. }
  140. func checkSingleCondition(jsonStr string, condition ConditionOperation) (bool, error) {
  141. // 处理负数索引
  142. path := processNegativeIndex(jsonStr, condition.Path)
  143. value := gjson.Get(jsonStr, path)
  144. if !value.Exists() {
  145. if condition.PassMissingKey {
  146. return true, nil
  147. }
  148. return false, nil
  149. }
  150. // 利用gjson的类型解析
  151. targetBytes, err := json.Marshal(condition.Value)
  152. if err != nil {
  153. return false, fmt.Errorf("failed to marshal condition value: %v", err)
  154. }
  155. targetValue := gjson.ParseBytes(targetBytes)
  156. result, err := compareGjsonValues(value, targetValue, strings.ToLower(condition.Mode))
  157. if err != nil {
  158. return false, fmt.Errorf("comparison failed for path %s: %v", condition.Path, err)
  159. }
  160. if condition.Invert {
  161. result = !result
  162. }
  163. return result, nil
  164. }
  165. func processNegativeIndex(jsonStr string, path string) string {
  166. re := regexp.MustCompile(`\.(-\d+)`)
  167. matches := re.FindAllStringSubmatch(path, -1)
  168. if len(matches) == 0 {
  169. return path
  170. }
  171. result := path
  172. for _, match := range matches {
  173. negIndex := match[1]
  174. index, _ := strconv.Atoi(negIndex)
  175. arrayPath := strings.Split(path, negIndex)[0]
  176. if strings.HasSuffix(arrayPath, ".") {
  177. arrayPath = arrayPath[:len(arrayPath)-1]
  178. }
  179. array := gjson.Get(jsonStr, arrayPath)
  180. if array.IsArray() {
  181. length := len(array.Array())
  182. actualIndex := length + index
  183. if actualIndex >= 0 && actualIndex < length {
  184. result = strings.Replace(result, match[0], "."+strconv.Itoa(actualIndex), 1)
  185. }
  186. }
  187. }
  188. return result
  189. }
  190. // compareGjsonValues 直接比较两个gjson.Result,支持所有比较模式
  191. func compareGjsonValues(jsonValue, targetValue gjson.Result, mode string) (bool, error) {
  192. switch mode {
  193. case "full":
  194. return compareEqual(jsonValue, targetValue)
  195. case "prefix":
  196. return strings.HasPrefix(jsonValue.String(), targetValue.String()), nil
  197. case "suffix":
  198. return strings.HasSuffix(jsonValue.String(), targetValue.String()), nil
  199. case "contains":
  200. return strings.Contains(jsonValue.String(), targetValue.String()), nil
  201. case "gt":
  202. return compareNumeric(jsonValue, targetValue, "gt")
  203. case "gte":
  204. return compareNumeric(jsonValue, targetValue, "gte")
  205. case "lt":
  206. return compareNumeric(jsonValue, targetValue, "lt")
  207. case "lte":
  208. return compareNumeric(jsonValue, targetValue, "lte")
  209. default:
  210. return false, fmt.Errorf("unsupported comparison mode: %s", mode)
  211. }
  212. }
  213. func compareEqual(jsonValue, targetValue gjson.Result) (bool, error) {
  214. // 对null值特殊处理:两个都是null返回true,一个是null另一个不是返回false
  215. if jsonValue.Type == gjson.Null || targetValue.Type == gjson.Null {
  216. return jsonValue.Type == gjson.Null && targetValue.Type == gjson.Null, nil
  217. }
  218. // 对布尔值特殊处理
  219. if (jsonValue.Type == gjson.True || jsonValue.Type == gjson.False) &&
  220. (targetValue.Type == gjson.True || targetValue.Type == gjson.False) {
  221. return jsonValue.Bool() == targetValue.Bool(), nil
  222. }
  223. // 如果类型不同,报错
  224. if jsonValue.Type != targetValue.Type {
  225. return false, fmt.Errorf("compare for different types, got %v and %v", jsonValue.Type, targetValue.Type)
  226. }
  227. switch jsonValue.Type {
  228. case gjson.True, gjson.False:
  229. return jsonValue.Bool() == targetValue.Bool(), nil
  230. case gjson.Number:
  231. return jsonValue.Num == targetValue.Num, nil
  232. case gjson.String:
  233. return jsonValue.String() == targetValue.String(), nil
  234. default:
  235. return jsonValue.String() == targetValue.String(), nil
  236. }
  237. }
  238. func compareNumeric(jsonValue, targetValue gjson.Result, operator string) (bool, error) {
  239. // 只有数字类型才支持数值比较
  240. if jsonValue.Type != gjson.Number || targetValue.Type != gjson.Number {
  241. return false, fmt.Errorf("numeric comparison requires both values to be numbers, got %v and %v", jsonValue.Type, targetValue.Type)
  242. }
  243. jsonNum := jsonValue.Num
  244. targetNum := targetValue.Num
  245. switch operator {
  246. case "gt":
  247. return jsonNum > targetNum, nil
  248. case "gte":
  249. return jsonNum >= targetNum, nil
  250. case "lt":
  251. return jsonNum < targetNum, nil
  252. case "lte":
  253. return jsonNum <= targetNum, nil
  254. default:
  255. return false, fmt.Errorf("unsupported numeric operator: %s", operator)
  256. }
  257. }
  258. // applyOperationsLegacy 原参数覆盖方法
  259. func applyOperationsLegacy(jsonData []byte, paramOverride map[string]interface{}) ([]byte, error) {
  260. reqMap := make(map[string]interface{})
  261. err := json.Unmarshal(jsonData, &reqMap)
  262. if err != nil {
  263. return nil, err
  264. }
  265. for key, value := range paramOverride {
  266. reqMap[key] = value
  267. }
  268. return json.Marshal(reqMap)
  269. }
  270. func applyOperations(jsonStr string, operations []ParamOperation) (string, error) {
  271. result := jsonStr
  272. for _, op := range operations {
  273. // 检查条件是否满足
  274. ok, err := checkConditions(result, op.Conditions, op.Logic)
  275. if err != nil {
  276. return "", err
  277. }
  278. if !ok {
  279. continue // 条件不满足,跳过当前操作
  280. }
  281. // 处理路径中的负数索引
  282. opPath := processNegativeIndex(result, op.Path)
  283. opFrom := processNegativeIndex(result, op.From)
  284. opTo := processNegativeIndex(result, op.To)
  285. switch op.Mode {
  286. case "delete":
  287. result, err = sjson.Delete(result, opPath)
  288. case "set":
  289. if op.KeepOrigin && gjson.Get(result, opPath).Exists() {
  290. continue
  291. }
  292. result, err = sjson.Set(result, opPath, op.Value)
  293. case "move":
  294. result, err = moveValue(result, opFrom, opTo)
  295. case "prepend":
  296. result, err = modifyValue(result, opPath, op.Value, op.KeepOrigin, true)
  297. case "append":
  298. result, err = modifyValue(result, opPath, op.Value, op.KeepOrigin, false)
  299. default:
  300. return "", fmt.Errorf("unknown operation: %s", op.Mode)
  301. }
  302. if err != nil {
  303. return "", fmt.Errorf("operation %s failed: %v", op.Mode, err)
  304. }
  305. }
  306. return result, nil
  307. }
  308. func moveValue(jsonStr, fromPath, toPath string) (string, error) {
  309. sourceValue := gjson.Get(jsonStr, fromPath)
  310. if !sourceValue.Exists() {
  311. return jsonStr, fmt.Errorf("source path does not exist: %s", fromPath)
  312. }
  313. result, err := sjson.Set(jsonStr, toPath, sourceValue.Value())
  314. if err != nil {
  315. return "", err
  316. }
  317. return sjson.Delete(result, fromPath)
  318. }
  319. func modifyValue(jsonStr, path string, value interface{}, keepOrigin, isPrepend bool) (string, error) {
  320. current := gjson.Get(jsonStr, path)
  321. switch {
  322. case current.IsArray():
  323. return modifyArray(jsonStr, path, value, isPrepend)
  324. case current.Type == gjson.String:
  325. return modifyString(jsonStr, path, value, isPrepend)
  326. case current.Type == gjson.JSON:
  327. return mergeObjects(jsonStr, path, value, keepOrigin)
  328. }
  329. return jsonStr, fmt.Errorf("operation not supported for type: %v", current.Type)
  330. }
  331. func modifyArray(jsonStr, path string, value interface{}, isPrepend bool) (string, error) {
  332. current := gjson.Get(jsonStr, path)
  333. var newArray []interface{}
  334. // 添加新值
  335. addValue := func() {
  336. if arr, ok := value.([]interface{}); ok {
  337. newArray = append(newArray, arr...)
  338. } else {
  339. newArray = append(newArray, value)
  340. }
  341. }
  342. // 添加原值
  343. addOriginal := func() {
  344. current.ForEach(func(_, val gjson.Result) bool {
  345. newArray = append(newArray, val.Value())
  346. return true
  347. })
  348. }
  349. if isPrepend {
  350. addValue()
  351. addOriginal()
  352. } else {
  353. addOriginal()
  354. addValue()
  355. }
  356. return sjson.Set(jsonStr, path, newArray)
  357. }
  358. func modifyString(jsonStr, path string, value interface{}, isPrepend bool) (string, error) {
  359. current := gjson.Get(jsonStr, path)
  360. valueStr := fmt.Sprintf("%v", value)
  361. var newStr string
  362. if isPrepend {
  363. newStr = valueStr + current.String()
  364. } else {
  365. newStr = current.String() + valueStr
  366. }
  367. return sjson.Set(jsonStr, path, newStr)
  368. }
  369. func mergeObjects(jsonStr, path string, value interface{}, keepOrigin bool) (string, error) {
  370. current := gjson.Get(jsonStr, path)
  371. var currentMap, newMap map[string]interface{}
  372. // 解析当前值
  373. if err := json.Unmarshal([]byte(current.Raw), &currentMap); err != nil {
  374. return "", err
  375. }
  376. // 解析新值
  377. switch v := value.(type) {
  378. case map[string]interface{}:
  379. newMap = v
  380. default:
  381. jsonBytes, _ := json.Marshal(v)
  382. if err := json.Unmarshal(jsonBytes, &newMap); err != nil {
  383. return "", err
  384. }
  385. }
  386. // 合并
  387. result := make(map[string]interface{})
  388. for k, v := range currentMap {
  389. result[k] = v
  390. }
  391. for k, v := range newMap {
  392. if !keepOrigin || result[k] == nil {
  393. result[k] = v
  394. }
  395. }
  396. return sjson.Set(jsonStr, path, result)
  397. }