delta.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package formatter
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. diff "github.com/yudai/gojsondiff"
  7. )
  8. const (
  9. DeltaDelete = 0
  10. DeltaTextDiff = 2
  11. DeltaMove = 3
  12. )
  13. func NewDeltaFormatter() *DeltaFormatter {
  14. return &DeltaFormatter{
  15. PrintIndent: true,
  16. }
  17. }
  18. type DeltaFormatter struct {
  19. PrintIndent bool
  20. }
  21. func (f *DeltaFormatter) Format(diff diff.Diff) (result string, err error) {
  22. jsonObject, err := f.formatObject(diff.Deltas())
  23. if err != nil {
  24. return "", err
  25. }
  26. var resultBytes []byte
  27. if f.PrintIndent {
  28. resultBytes, err = json.MarshalIndent(jsonObject, "", " ")
  29. } else {
  30. resultBytes, err = json.Marshal(jsonObject)
  31. }
  32. if err != nil {
  33. return "", err
  34. }
  35. return string(resultBytes) + "\n", nil
  36. }
  37. func (f *DeltaFormatter) FormatAsJson(diff diff.Diff) (json map[string]interface{}, err error) {
  38. return f.formatObject(diff.Deltas())
  39. }
  40. func (f *DeltaFormatter) formatObject(deltas []diff.Delta) (deltaJson map[string]interface{}, err error) {
  41. deltaJson = map[string]interface{}{}
  42. for _, delta := range deltas {
  43. switch delta.(type) {
  44. case *diff.Object:
  45. d := delta.(*diff.Object)
  46. deltaJson[d.Position.String()], err = f.formatObject(d.Deltas)
  47. if err != nil {
  48. return nil, err
  49. }
  50. case *diff.Array:
  51. d := delta.(*diff.Array)
  52. deltaJson[d.Position.String()], err = f.formatArray(d.Deltas)
  53. if err != nil {
  54. return nil, err
  55. }
  56. case *diff.Added:
  57. d := delta.(*diff.Added)
  58. deltaJson[d.PostPosition().String()] = []interface{}{d.Value}
  59. case *diff.Modified:
  60. d := delta.(*diff.Modified)
  61. deltaJson[d.PostPosition().String()] = []interface{}{d.OldValue, d.NewValue}
  62. case *diff.TextDiff:
  63. d := delta.(*diff.TextDiff)
  64. deltaJson[d.PostPosition().String()] = []interface{}{d.DiffString(), 0, DeltaTextDiff}
  65. case *diff.Deleted:
  66. d := delta.(*diff.Deleted)
  67. deltaJson[d.PrePosition().String()] = []interface{}{d.Value, 0, DeltaDelete}
  68. case *diff.Moved:
  69. return nil, errors.New("Delta type 'Move' is not supported in objects")
  70. default:
  71. return nil, errors.New(fmt.Sprintf("Unknown Delta type detected: %#v", delta))
  72. }
  73. }
  74. return
  75. }
  76. func (f *DeltaFormatter) formatArray(deltas []diff.Delta) (deltaJson map[string]interface{}, err error) {
  77. deltaJson = map[string]interface{}{
  78. "_t": "a",
  79. }
  80. for _, delta := range deltas {
  81. switch delta.(type) {
  82. case *diff.Object:
  83. d := delta.(*diff.Object)
  84. deltaJson[d.Position.String()], err = f.formatObject(d.Deltas)
  85. if err != nil {
  86. return nil, err
  87. }
  88. case *diff.Array:
  89. d := delta.(*diff.Array)
  90. deltaJson[d.Position.String()], err = f.formatArray(d.Deltas)
  91. if err != nil {
  92. return nil, err
  93. }
  94. case *diff.Added:
  95. d := delta.(*diff.Added)
  96. deltaJson[d.PostPosition().String()] = []interface{}{d.Value}
  97. case *diff.Modified:
  98. d := delta.(*diff.Modified)
  99. deltaJson[d.PostPosition().String()] = []interface{}{d.OldValue, d.NewValue}
  100. case *diff.TextDiff:
  101. d := delta.(*diff.TextDiff)
  102. deltaJson[d.PostPosition().String()] = []interface{}{d.DiffString(), 0, DeltaTextDiff}
  103. case *diff.Deleted:
  104. d := delta.(*diff.Deleted)
  105. deltaJson["_"+d.PrePosition().String()] = []interface{}{d.Value, 0, DeltaDelete}
  106. case *diff.Moved:
  107. d := delta.(*diff.Moved)
  108. deltaJson["_"+d.PrePosition().String()] = []interface{}{"", d.PostPosition(), DeltaMove}
  109. default:
  110. return nil, errors.New(fmt.Sprintf("Unknown Delta type detected: %#v", delta))
  111. }
  112. }
  113. return
  114. }