merge.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright 2020 Jebbs. All rights reserved.
  2. // Use of this source code is governed by MIT
  3. // license that can be found in the LICENSE file.
  4. /*
  5. Package merge provides the capbility to merge multiple
  6. JSON files or contents into one output.
  7. Merge Rules:
  8. - Simple values (string, number, boolean) are overwritten, others are merged
  9. - Elements with same "tag" (or "_tag") in an array will be merged
  10. - Add "_priority" property to array elements will help sort the
  11. */
  12. package merge
  13. import (
  14. "bytes"
  15. "encoding/json"
  16. "io"
  17. "github.com/v2fly/v2ray-core/v4/common/cmdarg"
  18. "github.com/v2fly/v2ray-core/v4/infra/conf/serial"
  19. )
  20. // FilesToJSON merges multiple jsons files into one json, accepts remote url, or local file path
  21. func FilesToJSON(args []string) ([]byte, error) {
  22. m, err := FilesToMap(args)
  23. if err != nil {
  24. return nil, err
  25. }
  26. return json.Marshal(m)
  27. }
  28. // BytesToJSON merges multiple json contents into one json.
  29. func BytesToJSON(args [][]byte) ([]byte, error) {
  30. m, err := BytesToMap(args)
  31. if err != nil {
  32. return nil, err
  33. }
  34. return json.Marshal(m)
  35. }
  36. // FilesToMap merges multiple json files into one map, accepts remote url, or local file path
  37. func FilesToMap(args []string) (m map[string]interface{}, err error) {
  38. m, err = loadFiles(args)
  39. if err != nil {
  40. return nil, err
  41. }
  42. err = applyRules(m)
  43. if err != nil {
  44. return nil, err
  45. }
  46. return m, nil
  47. }
  48. // BytesToMap merges multiple json contents into one map.
  49. func BytesToMap(args [][]byte) (m map[string]interface{}, err error) {
  50. m, err = loadBytes(args)
  51. if err != nil {
  52. return nil, err
  53. }
  54. err = applyRules(m)
  55. if err != nil {
  56. return nil, err
  57. }
  58. return m, nil
  59. }
  60. func loadFiles(args []string) (map[string]interface{}, error) {
  61. c := make(map[string]interface{})
  62. for _, arg := range args {
  63. r, err := cmdarg.LoadArg(arg)
  64. if err != nil {
  65. return nil, err
  66. }
  67. m, err := decode(r)
  68. if err != nil {
  69. return nil, err
  70. }
  71. if err = mergeMaps(c, m); err != nil {
  72. return nil, err
  73. }
  74. }
  75. return c, nil
  76. }
  77. func loadBytes(args [][]byte) (map[string]interface{}, error) {
  78. conf := make(map[string]interface{})
  79. for _, arg := range args {
  80. r := bytes.NewReader(arg)
  81. m, err := decode(r)
  82. if err != nil {
  83. return nil, err
  84. }
  85. if err = mergeMaps(conf, m); err != nil {
  86. return nil, err
  87. }
  88. }
  89. return conf, nil
  90. }
  91. func decode(r io.Reader) (map[string]interface{}, error) {
  92. c := make(map[string]interface{})
  93. err := serial.DecodeJSON(r, &c)
  94. if err != nil {
  95. return nil, err
  96. }
  97. return c, nil
  98. }