merge.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. "fmt"
  17. "io"
  18. "github.com/v2fly/v2ray-core/v4/common/cmdarg"
  19. "github.com/v2fly/v2ray-core/v4/infra/conf/serial"
  20. )
  21. // FilesToJSON merges multiple jsons files into one json, accepts remote url, or local file path
  22. func FilesToJSON(args []string) ([]byte, error) {
  23. m, err := FilesToMap(args)
  24. if err != nil {
  25. return nil, err
  26. }
  27. return json.Marshal(m)
  28. }
  29. // BytesToJSON merges multiple json contents into one json.
  30. func BytesToJSON(args [][]byte) ([]byte, error) {
  31. m, err := BytesToMap(args)
  32. if err != nil {
  33. return nil, err
  34. }
  35. return json.Marshal(m)
  36. }
  37. // FilesToMap merges multiple json files into one map, accepts remote url, or local file path
  38. func FilesToMap(args []string) (m map[string]interface{}, err error) {
  39. m, err = loadFiles(args)
  40. if err != nil {
  41. return nil, err
  42. }
  43. err = applyRules(m)
  44. if err != nil {
  45. return nil, err
  46. }
  47. return m, nil
  48. }
  49. // BytesToMap merges multiple json contents into one map.
  50. func BytesToMap(args [][]byte) (m map[string]interface{}, err error) {
  51. m, err = loadBytes(args)
  52. if err != nil {
  53. return nil, err
  54. }
  55. err = applyRules(m)
  56. if err != nil {
  57. return nil, err
  58. }
  59. return m, nil
  60. }
  61. func loadFiles(args []string) (map[string]interface{}, error) {
  62. c := make(map[string]interface{})
  63. for _, arg := range args {
  64. r, err := cmdarg.LoadArg(arg)
  65. if err != nil {
  66. return nil, fmt.Errorf("fail to load %s: %s", arg, err)
  67. }
  68. m, err := decode(r)
  69. if err != nil {
  70. return nil, fmt.Errorf("fail to decode %s: %s", arg, err)
  71. }
  72. if err = mergeMaps(c, m); err != nil {
  73. return nil, fmt.Errorf("fail to merge %s: %s", arg, err)
  74. }
  75. }
  76. return c, nil
  77. }
  78. func loadBytes(args [][]byte) (map[string]interface{}, error) {
  79. conf := make(map[string]interface{})
  80. for _, arg := range args {
  81. r := bytes.NewReader(arg)
  82. m, err := decode(r)
  83. if err != nil {
  84. return nil, err
  85. }
  86. if err = mergeMaps(conf, m); err != nil {
  87. return nil, err
  88. }
  89. }
  90. return conf, nil
  91. }
  92. func decode(r io.Reader) (map[string]interface{}, error) {
  93. c := make(map[string]interface{})
  94. err := serial.DecodeJSON(r, &c)
  95. if err != nil {
  96. return nil, err
  97. }
  98. return c, nil
  99. }