@@ -315,85 +315,133 @@ func IsEqualObject(a, b utils.NavigableMap[string, JsonType]) bool {
315315// MergeObject merges two JSON objects into a new JSON object.
316316// If the same value, that is not an object or an array exists in both objects, the value from the second object will be used.
317317func MergeObject (template , parent * JsonObject , keepOverrides bool , path string ) * JsonObject {
318- result := NewJsonObject ()
319- for _ , k := range template .Keys () {
320- v := template .Get (k )
321- if IsObject (v ) {
322- result .Put (k , DeepCopyObject (AsObject (v )))
323- } else if IsArray (v ) {
324- result .Put (k , DeepCopyArray (AsArray (v )))
325- } else {
326- result .Put (k , v )
318+ if template == nil {
319+ template = NewJsonObject ()
320+ }
321+ if parent == nil {
322+ parent = NewJsonObject ()
323+ }
324+ templateCapacity := 0
325+ if template .Value != nil {
326+ templateCapacity = template .Value .Size ()
327+ }
328+ parentCapacity := 0
329+ if parent .Value != nil {
330+ parentCapacity = parent .Value .Size ()
331+ }
332+ result := NewJsonObjectWithCapacity (templateCapacity + parentCapacity )
333+ for _ , key := range template .Keys () {
334+ value := template .Get (key )
335+ switch typed := value .(type ) {
336+ case * JsonObject :
337+ result .Put (key , DeepCopyObject (typed ))
338+ case * JsonArray :
339+ result .Put (key , DeepCopyArray (typed ))
340+ default :
341+ result .Put (key , value )
327342 }
328343 }
329- skipKeys := make (map [string ]struct {})
330- out:
331- for _ , k := range parent .Keys () {
332- v := parent .Get (k )
333- if _ , ok := skipKeys [k ]; ok {
334- continue out
344+ skipKeys := make (map [string ]struct {}, parentCapacity )
345+ for _ , rawKey := range parent .Keys () {
346+ if _ , ok := skipKeys [rawKey ]; ok {
347+ continue
348+ }
349+ value := parent .Get (rawKey )
350+ isReversedMerge := len (rawKey ) > 0 && rawKey [0 ] == '^'
351+ key := rawKey
352+ if isReversedMerge {
353+ key = rawKey [1 :]
335354 }
336- isReversedMerge := strings .HasPrefix (k , "^" )
337- k = strings .TrimPrefix (k , "^" )
338- if strings .HasPrefix (k , "$" ) && ! IsReservedKey (k ) {
339- trimmedKey := strings .TrimPrefix (k , "$" )
355+ if len (key ) == 0 {
356+ continue
357+ }
358+ if key [0 ] == '$' && ! IsReservedKey (key ) {
359+ trimmedKey := key [1 :]
340360 if keepOverrides {
341- result .Put (k , v )
361+ result .Put (key , value )
342362 } else {
343- if IsObject (v ) {
344- result .Put (trimmedKey , MergeObject (NewJsonObject (), AsObject (v ), keepOverrides , joinObjectPath (path , k )))
345- } else if IsArray (v ) {
346- result .Put (trimmedKey , MergeArray (NewJsonArray (), AsArray (v ), keepOverrides , joinObjectPath (path , k )))
347- } else {
348- result .Put (trimmedKey , v )
363+ childPath := joinObjectPath (path , key )
364+ switch typed := value .(type ) {
365+ case * JsonObject :
366+ childCapacity := 0
367+ if typed != nil {
368+ childCapacity = typed .Size ()
369+ }
370+ result .Put (trimmedKey , MergeObject (NewJsonObjectWithCapacity (childCapacity ), typed , keepOverrides , childPath ))
371+ case * JsonArray :
372+ childCapacity := 0
373+ if typed != nil {
374+ childCapacity = len (typed .Value )
375+ }
376+ result .Put (trimmedKey , MergeArray (NewJsonArrayWithCapacity (childCapacity ), typed , keepOverrides , childPath ))
377+ default :
378+ result .Put (trimmedKey , value )
349379 }
350380 }
351381 skipKeys [trimmedKey ] = struct {}{}
352- } else if ! template .ContainsKey (k ) {
353- if IsObject (v ) {
354- merge := MergeObject (NewJsonObject (), AsObject (v ), keepOverrides , joinObjectPath (path , k ))
355- result .Put (k , merge )
356- } else if IsArray (v ) {
357- merge := MergeArray (NewJsonArray (), AsArray (v ), keepOverrides , joinObjectPath (path , k ))
358- result .Put (k , merge )
382+ continue
383+ }
384+ templateValue , exists := template .TryGet (key )
385+ if ! exists {
386+ childPath := joinObjectPath (path , key )
387+ switch typed := value .(type ) {
388+ case * JsonObject :
389+ childCapacity := 0
390+ if typed != nil {
391+ childCapacity = typed .Size ()
392+ }
393+ result .Put (key , MergeObject (NewJsonObjectWithCapacity (childCapacity ), typed , keepOverrides , childPath ))
394+ case * JsonArray :
395+ childCapacity := 0
396+ if typed != nil {
397+ childCapacity = len (typed .Value )
398+ }
399+ result .Put (key , MergeArray (NewJsonArrayWithCapacity (childCapacity ), typed , keepOverrides , childPath ))
400+ default :
401+ result .Put (key , value )
402+ }
403+ continue
404+ }
405+ childPath := joinObjectPath (path , key )
406+ switch typed := value .(type ) {
407+ case * JsonObject :
408+ if templateObj , ok := templateValue .(* JsonObject ); ok {
409+ result .Put (key , MergeObject (templateObj , typed , keepOverrides , childPath ))
359410 } else {
360- result .Put (k , v )
411+ result .Put (key , value )
361412 }
362- } else {
363- if IsObject (v ) && IsObject (result .Get (k )) {
364- merge := MergeObject (AsObject (template .Get (k )), AsObject (v ), keepOverrides , joinObjectPath (path , k ))
365- result .Put (k , merge )
366- } else if IsArray (v ) && IsArray (template .Get (k )) {
367- var merge , v1 * JsonArray
368- if result .ContainsKey (k ) {
369- v1 = AsArray (result .Get (k ))
370- } else {
371- v1 = AsArray (template .Get (k ))
372- }
413+ case * JsonArray :
414+ if _ , ok := templateValue .(* JsonArray ); ok {
415+ base := AsArray (result .Get (key ))
373416 if isReversedMerge {
374- merge = MergeArray (AsArray ( v ), v1 , keepOverrides , joinObjectPath ( path , k ))
417+ result . Put ( key , MergeArray (typed , base , keepOverrides , childPath ))
375418 } else {
376- merge = MergeArray (v1 , AsArray ( v ) , keepOverrides , joinObjectPath ( path , k ))
419+ result . Put ( key , MergeArray (base , typed , keepOverrides , childPath ))
377420 }
378- result .Put (k , merge )
379421 } else {
380- result .Put (k , v )
422+ result .Put (key , value )
381423 }
424+ default :
425+ result .Put (key , value )
382426 }
383427 }
384428 return result
385429}
386430
387431// DeepCopyObject creates a deep copy of the given JSON object.
388432func DeepCopyObject (object * JsonObject ) * JsonObject {
389- result := NewJsonObject ()
433+ if object == nil {
434+ return NewJsonObject ()
435+ }
436+ result := NewJsonObjectWithCapacity (object .Size ())
390437 for _ , k := range object .Keys () {
391438 v := object .Get (k )
392- if IsObject (v ) {
393- result .Put (k , DeepCopyObject (AsObject (v )))
394- } else if IsArray (v ) {
395- result .Put (k , DeepCopyArray (AsArray (v )))
396- } else {
439+ switch typed := v .(type ) {
440+ case * JsonObject :
441+ result .Put (k , DeepCopyObject (typed ))
442+ case * JsonArray :
443+ result .Put (k , DeepCopyArray (typed ))
444+ default :
397445 result .Put (k , v )
398446 }
399447 }
0 commit comments