merge.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package badjsonmerge
  2. import (
  3. "encoding/json"
  4. "reflect"
  5. "github.com/sagernet/sing-box/common/badjson"
  6. "github.com/sagernet/sing-box/option"
  7. E "github.com/sagernet/sing/common/exceptions"
  8. )
  9. func MergeOptions(source option.Options, destination option.Options) (option.Options, error) {
  10. rawSource, err := json.Marshal(source)
  11. if err != nil {
  12. return option.Options{}, E.Cause(err, "marshal source")
  13. }
  14. rawDestination, err := json.Marshal(destination)
  15. if err != nil {
  16. return option.Options{}, E.Cause(err, "marshal destination")
  17. }
  18. rawMerged, err := MergeJSON(rawSource, rawDestination)
  19. if err != nil {
  20. return option.Options{}, E.Cause(err, "merge options")
  21. }
  22. var merged option.Options
  23. err = json.Unmarshal(rawMerged, &merged)
  24. if err != nil {
  25. return option.Options{}, E.Cause(err, "unmarshal merged options")
  26. }
  27. return merged, nil
  28. }
  29. func MergeJSON(rawSource json.RawMessage, rawDestination json.RawMessage) (json.RawMessage, error) {
  30. source, err := badjson.Decode(rawSource)
  31. if err != nil {
  32. return nil, E.Cause(err, "decode source")
  33. }
  34. destination, err := badjson.Decode(rawDestination)
  35. if err != nil {
  36. return nil, E.Cause(err, "decode destination")
  37. }
  38. merged, err := mergeJSON(source, destination)
  39. if err != nil {
  40. return nil, err
  41. }
  42. return json.Marshal(merged)
  43. }
  44. func mergeJSON(anySource any, anyDestination any) (any, error) {
  45. switch destination := anyDestination.(type) {
  46. case badjson.JSONArray:
  47. switch source := anySource.(type) {
  48. case badjson.JSONArray:
  49. destination = append(destination, source...)
  50. default:
  51. destination = append(destination, source)
  52. }
  53. return destination, nil
  54. case *badjson.JSONObject:
  55. switch source := anySource.(type) {
  56. case *badjson.JSONObject:
  57. for _, entry := range source.Entries() {
  58. oldValue, loaded := destination.Get(entry.Key)
  59. if loaded {
  60. var err error
  61. entry.Value, err = mergeJSON(entry.Value, oldValue)
  62. if err != nil {
  63. return nil, E.Cause(err, "merge object item ", entry.Key)
  64. }
  65. }
  66. destination.Put(entry.Key, entry.Value)
  67. }
  68. default:
  69. return nil, E.New("cannot merge json object into ", reflect.TypeOf(destination))
  70. }
  71. return destination, nil
  72. default:
  73. return destination, nil
  74. }
  75. }