Skip to content

Commit 6910b4d

Browse files
committed
refactor: skip merge, if there is no need for merge
1 parent 88404da commit 6910b4d

3 files changed

Lines changed: 93 additions & 31 deletions

File tree

jsonte/types/array.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -203,20 +203,12 @@ func MergeArray(template, parent *JsonArray, keepOverrides bool, path string) *J
203203
parent = NewJsonArray()
204204
}
205205
result := &JsonArray{Value: make([]JsonType, 0, len(template.Value)+len(parent.Value))}
206-
for idx, v := range template.Value {
206+
for _, v := range template.Value {
207207
switch typed := v.(type) {
208208
case *JsonObject:
209-
childCapacity := 0
210-
if typed != nil {
211-
childCapacity = typed.Size()
212-
}
213-
result.Value = append(result.Value, MergeObject(NewJsonObjectWithCapacity(childCapacity), typed, keepOverrides, joinArrayPath(path, idx)))
209+
result.Value = append(result.Value, DeepCopyObject(typed))
214210
case *JsonArray:
215-
childCapacity := 0
216-
if typed != nil {
217-
childCapacity = len(typed.Value)
218-
}
219-
result.Value = append(result.Value, MergeArray(NewJsonArrayWithCapacity(childCapacity), typed, keepOverrides, joinArrayPath(path, idx)))
211+
result.Value = append(result.Value, DeepCopyArray(typed))
220212
default:
221213
result.Value = append(result.Value, v)
222214
}
@@ -228,13 +220,21 @@ func MergeArray(template, parent *JsonArray, keepOverrides bool, path string) *J
228220
if typed != nil {
229221
childCapacity = typed.Size()
230222
}
231-
result.Value = append(result.Value, MergeObject(NewJsonObjectWithCapacity(childCapacity), typed, keepOverrides, joinArrayPath(path, idx)))
223+
if typed != nil && objectNeedsMergeProcessing(typed) {
224+
result.Value = append(result.Value, MergeObject(NewJsonObjectWithCapacity(childCapacity), typed, keepOverrides, joinArrayPath(path, idx)))
225+
} else {
226+
result.Value = append(result.Value, DeepCopyObject(typed))
227+
}
232228
case *JsonArray:
233229
childCapacity := 0
234230
if typed != nil {
235231
childCapacity = len(typed.Value)
236232
}
237-
result.Value = append(result.Value, MergeArray(NewJsonArrayWithCapacity(childCapacity), typed, keepOverrides, joinArrayPath(path, idx)))
233+
if typed != nil && arrayNeedsMergeProcessing(typed) {
234+
result.Value = append(result.Value, MergeArray(NewJsonArrayWithCapacity(childCapacity), typed, keepOverrides, joinArrayPath(path, idx)))
235+
} else {
236+
result.Value = append(result.Value, DeepCopyArray(typed))
237+
}
238238
default:
239239
result.Value = append(result.Value, v)
240240
}

jsonte/types/merge_helpers.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,60 @@ func joinObjectPath(path, key string) string {
1111
func joinArrayPath(path string, idx int) string {
1212
return path + "[" + strconv.Itoa(idx) + "]"
1313
}
14+
15+
func objectNeedsMergeProcessing(obj *JsonObject) bool {
16+
if obj == nil || obj.Size() == 0 {
17+
return false
18+
}
19+
stack := []*JsonObject{obj}
20+
for len(stack) > 0 {
21+
current := stack[len(stack)-1]
22+
stack = stack[:len(stack)-1]
23+
if current == nil {
24+
continue
25+
}
26+
keys := current.Keys()
27+
for _, key := range keys {
28+
if key == "" {
29+
continue
30+
}
31+
if key[0] == '^' || (key[0] == '$' && !IsReservedKey(key)) {
32+
return true
33+
}
34+
switch typed := current.Get(key).(type) {
35+
case *JsonObject:
36+
stack = append(stack, typed)
37+
case *JsonArray:
38+
if arrayNeedsMergeProcessing(typed) {
39+
return true
40+
}
41+
}
42+
}
43+
}
44+
return false
45+
}
46+
47+
func arrayNeedsMergeProcessing(arr *JsonArray) bool {
48+
if arr == nil || len(arr.Value) == 0 {
49+
return false
50+
}
51+
stack := []*JsonArray{arr}
52+
for len(stack) > 0 {
53+
current := stack[len(stack)-1]
54+
stack = stack[:len(stack)-1]
55+
if current == nil {
56+
continue
57+
}
58+
for _, item := range current.Value {
59+
switch typed := item.(type) {
60+
case *JsonObject:
61+
if objectNeedsMergeProcessing(typed) {
62+
return true
63+
}
64+
case *JsonArray:
65+
stack = append(stack, typed)
66+
}
67+
}
68+
}
69+
return false
70+
}

jsonte/types/object.go

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -379,26 +379,29 @@ func MergeObject(template, parent *JsonObject, keepOverrides bool, path string)
379379
if keepOverrides {
380380
result.Put(key, value)
381381
} else {
382-
childPath := ""
383382
switch typed := value.(type) {
384383
case *JsonObject:
385384
childCapacity := 0
386385
if typed != nil {
387386
childCapacity = typed.Size()
388387
}
389-
if typed != nil {
390-
childPath = joinObjectPath(path, key)
388+
if typed != nil && objectNeedsMergeProcessing(typed) {
389+
childPath := joinObjectPath(path, key)
390+
result.Put(trimmedKey, MergeObject(NewJsonObjectWithCapacity(childCapacity), typed, keepOverrides, childPath))
391+
} else {
392+
result.Put(trimmedKey, DeepCopyObject(typed))
391393
}
392-
result.Put(trimmedKey, MergeObject(NewJsonObjectWithCapacity(childCapacity), typed, keepOverrides, childPath))
393394
case *JsonArray:
394395
childCapacity := 0
395396
if typed != nil {
396397
childCapacity = len(typed.Value)
397398
}
398-
if typed != nil {
399-
childPath = joinObjectPath(path, key)
399+
if typed != nil && arrayNeedsMergeProcessing(typed) {
400+
childPath := joinObjectPath(path, key)
401+
result.Put(trimmedKey, MergeArray(NewJsonArrayWithCapacity(childCapacity), typed, keepOverrides, childPath))
402+
} else {
403+
result.Put(trimmedKey, DeepCopyArray(typed))
400404
}
401-
result.Put(trimmedKey, MergeArray(NewJsonArrayWithCapacity(childCapacity), typed, keepOverrides, childPath))
402405
default:
403406
result.Put(trimmedKey, value)
404407
}
@@ -414,26 +417,29 @@ func MergeObject(template, parent *JsonObject, keepOverrides bool, path string)
414417
}
415418
baseValue, exists := result.TryGet(key)
416419
if !exists {
417-
childPath := ""
418420
switch typed := value.(type) {
419421
case *JsonObject:
420422
childCapacity := 0
421423
if typed != nil {
422424
childCapacity = typed.Size()
423425
}
424-
if typed != nil {
425-
childPath = joinObjectPath(path, key)
426+
if typed != nil && objectNeedsMergeProcessing(typed) {
427+
childPath := joinObjectPath(path, key)
428+
result.Put(key, MergeObject(NewJsonObjectWithCapacity(childCapacity), typed, keepOverrides, childPath))
429+
} else {
430+
result.Put(key, DeepCopyObject(typed))
426431
}
427-
result.Put(key, MergeObject(NewJsonObjectWithCapacity(childCapacity), typed, keepOverrides, childPath))
428432
case *JsonArray:
429433
childCapacity := 0
430434
if typed != nil {
431435
childCapacity = len(typed.Value)
432436
}
433-
if typed != nil {
434-
childPath = joinObjectPath(path, key)
437+
if typed != nil && arrayNeedsMergeProcessing(typed) {
438+
childPath := joinObjectPath(path, key)
439+
result.Put(key, MergeArray(NewJsonArrayWithCapacity(childCapacity), typed, keepOverrides, childPath))
440+
} else {
441+
result.Put(key, DeepCopyArray(typed))
435442
}
436-
result.Put(key, MergeArray(NewJsonArrayWithCapacity(childCapacity), typed, keepOverrides, childPath))
437443
default:
438444
result.Put(key, value)
439445
}
@@ -448,13 +454,12 @@ func MergeObject(template, parent *JsonObject, keepOverrides bool, path string)
448454
result.Put(key, value)
449455
}
450456
case *JsonArray:
451-
if _, ok := baseValue.(*JsonArray); ok {
452-
base := AsArray(result.Get(key))
457+
if baseArray, ok := baseValue.(*JsonArray); ok {
453458
childPath := joinObjectPath(path, key)
454459
if isReversedMerge {
455-
result.Put(key, MergeArray(typed, base, keepOverrides, childPath))
460+
result.Put(key, MergeArray(typed, baseArray, keepOverrides, childPath))
456461
} else {
457-
result.Put(key, MergeArray(base, typed, keepOverrides, childPath))
462+
result.Put(key, MergeArray(baseArray, typed, keepOverrides, childPath))
458463
}
459464
} else {
460465
result.Put(key, value)

0 commit comments

Comments
 (0)