unmarshaler.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package gojsondiff
  2. import (
  3. "encoding/json"
  4. "errors"
  5. dmp "github.com/sergi/go-diff/diffmatchpatch"
  6. "io"
  7. "strconv"
  8. )
  9. type Unmarshaller struct {
  10. }
  11. func NewUnmarshaller() *Unmarshaller {
  12. return &Unmarshaller{}
  13. }
  14. func (um *Unmarshaller) UnmarshalBytes(diffBytes []byte) (Diff, error) {
  15. var diffObj map[string]interface{}
  16. json.Unmarshal(diffBytes, &diffObj)
  17. return um.UnmarshalObject(diffObj)
  18. }
  19. func (um *Unmarshaller) UnmarshalString(diffString string) (Diff, error) {
  20. return um.UnmarshalBytes([]byte(diffString))
  21. }
  22. func (um *Unmarshaller) UnmarshalReader(diffReader io.Reader) (Diff, error) {
  23. var diffBytes []byte
  24. io.ReadFull(diffReader, diffBytes)
  25. return um.UnmarshalBytes(diffBytes)
  26. }
  27. func (um *Unmarshaller) UnmarshalObject(diffObj map[string]interface{}) (Diff, error) {
  28. result, err := process(Name(""), diffObj)
  29. if err != nil {
  30. return nil, err
  31. }
  32. return &diff{deltas: result.(*Object).Deltas}, nil
  33. }
  34. func process(position Position, object interface{}) (Delta, error) {
  35. var delta Delta
  36. switch object.(type) {
  37. case map[string]interface{}:
  38. o := object.(map[string]interface{})
  39. if isArray, typed := o["_t"]; typed && isArray == "a" {
  40. deltas := make([]Delta, 0, len(o))
  41. for name, value := range o {
  42. if name == "_t" {
  43. continue
  44. }
  45. normalizedName := name
  46. if normalizedName[0] == '_' {
  47. normalizedName = name[1:]
  48. }
  49. index, err := strconv.Atoi(normalizedName)
  50. if err != nil {
  51. return nil, err
  52. }
  53. childDelta, err := process(Index(index), value)
  54. if err != nil {
  55. return nil, err
  56. }
  57. deltas = append(deltas, childDelta)
  58. }
  59. for _, d := range deltas {
  60. switch d.(type) {
  61. case *Moved:
  62. moved := d.(*Moved)
  63. var dd interface{}
  64. var i int
  65. for i, dd = range deltas {
  66. switch dd.(type) {
  67. case *Moved:
  68. case PostDelta:
  69. pd := dd.(PostDelta)
  70. if moved.PostPosition() == pd.PostPosition() {
  71. moved.Delta = pd
  72. deltas = append(deltas[:i], deltas[i+1:]...)
  73. }
  74. }
  75. }
  76. }
  77. }
  78. delta = NewArray(position, deltas)
  79. } else {
  80. deltas := make([]Delta, 0, len(o))
  81. for name, value := range o {
  82. childDelta, err := process(Name(name), value)
  83. if err != nil {
  84. return nil, err
  85. }
  86. deltas = append(deltas, childDelta)
  87. }
  88. delta = NewObject(position, deltas)
  89. }
  90. case []interface{}:
  91. o := object.([]interface{})
  92. switch len(o) {
  93. case 1:
  94. delta = NewAdded(position, o[0])
  95. case 2:
  96. delta = NewModified(position, o[0], o[1])
  97. case 3:
  98. switch o[2] {
  99. case float64(0):
  100. delta = NewDeleted(position, o[0])
  101. case float64(2):
  102. dmp := dmp.New()
  103. patches, err := dmp.PatchFromText(o[0].(string))
  104. if err != nil {
  105. return nil, err
  106. }
  107. delta = NewTextDiff(position, patches, nil, nil)
  108. case float64(3):
  109. delta = NewMoved(position, Index(int(o[1].(float64))), nil, nil)
  110. default:
  111. return nil, errors.New("Unknown delta type")
  112. }
  113. }
  114. }
  115. return delta, nil
  116. }