File: delta.go

package info (click to toggle)
golang-github-yudai-gojsondiff 1.0.0%2Bgit20180504.0525c87-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 220 kB
  • sloc: makefile: 13
file content (124 lines) | stat: -rw-r--r-- 3,419 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package formatter

import (
	"encoding/json"
	"errors"
	"fmt"

	diff "github.com/yudai/gojsondiff"
)

const (
	DeltaDelete   = 0
	DeltaTextDiff = 2
	DeltaMove     = 3
)

func NewDeltaFormatter() *DeltaFormatter {
	return &DeltaFormatter{
		PrintIndent: true,
	}
}

type DeltaFormatter struct {
	PrintIndent bool
}

func (f *DeltaFormatter) Format(diff diff.Diff) (result string, err error) {
	jsonObject, err := f.formatObject(diff.Deltas())
	if err != nil {
		return "", err
	}
	var resultBytes []byte
	if f.PrintIndent {
		resultBytes, err = json.MarshalIndent(jsonObject, "", "  ")
	} else {
		resultBytes, err = json.Marshal(jsonObject)
	}
	if err != nil {
		return "", err
	}

	return string(resultBytes) + "\n", nil
}

func (f *DeltaFormatter) FormatAsJson(diff diff.Diff) (json map[string]interface{}, err error) {
	return f.formatObject(diff.Deltas())
}

func (f *DeltaFormatter) formatObject(deltas []diff.Delta) (deltaJson map[string]interface{}, err error) {
	deltaJson = map[string]interface{}{}
	for _, delta := range deltas {
		switch delta.(type) {
		case *diff.Object:
			d := delta.(*diff.Object)
			deltaJson[d.Position.String()], err = f.formatObject(d.Deltas)
			if err != nil {
				return nil, err
			}
		case *diff.Array:
			d := delta.(*diff.Array)
			deltaJson[d.Position.String()], err = f.formatArray(d.Deltas)
			if err != nil {
				return nil, err
			}
		case *diff.Added:
			d := delta.(*diff.Added)
			deltaJson[d.PostPosition().String()] = []interface{}{d.Value}
		case *diff.Modified:
			d := delta.(*diff.Modified)
			deltaJson[d.PostPosition().String()] = []interface{}{d.OldValue, d.NewValue}
		case *diff.TextDiff:
			d := delta.(*diff.TextDiff)
			deltaJson[d.PostPosition().String()] = []interface{}{d.DiffString(), 0, DeltaTextDiff}
		case *diff.Deleted:
			d := delta.(*diff.Deleted)
			deltaJson[d.PrePosition().String()] = []interface{}{d.Value, 0, DeltaDelete}
		case *diff.Moved:
			return nil, errors.New("Delta type 'Move' is not supported in objects")
		default:
			return nil, errors.New(fmt.Sprintf("Unknown Delta type detected: %#v", delta))
		}
	}
	return
}

func (f *DeltaFormatter) formatArray(deltas []diff.Delta) (deltaJson map[string]interface{}, err error) {
	deltaJson = map[string]interface{}{
		"_t": "a",
	}
	for _, delta := range deltas {
		switch delta.(type) {
		case *diff.Object:
			d := delta.(*diff.Object)
			deltaJson[d.Position.String()], err = f.formatObject(d.Deltas)
			if err != nil {
				return nil, err
			}
		case *diff.Array:
			d := delta.(*diff.Array)
			deltaJson[d.Position.String()], err = f.formatArray(d.Deltas)
			if err != nil {
				return nil, err
			}
		case *diff.Added:
			d := delta.(*diff.Added)
			deltaJson[d.PostPosition().String()] = []interface{}{d.Value}
		case *diff.Modified:
			d := delta.(*diff.Modified)
			deltaJson[d.PostPosition().String()] = []interface{}{d.OldValue, d.NewValue}
		case *diff.TextDiff:
			d := delta.(*diff.TextDiff)
			deltaJson[d.PostPosition().String()] = []interface{}{d.DiffString(), 0, DeltaTextDiff}
		case *diff.Deleted:
			d := delta.(*diff.Deleted)
			deltaJson["_"+d.PrePosition().String()] = []interface{}{d.Value, 0, DeltaDelete}
		case *diff.Moved:
			d := delta.(*diff.Moved)
			deltaJson["_"+d.PrePosition().String()] = []interface{}{"", d.PostPosition(), DeltaMove}
		default:
			return nil, errors.New(fmt.Sprintf("Unknown Delta type detected: %#v", delta))
		}
	}
	return
}