Deep Copy of Nested Maps and Lists in Groovy

Hi everyone,

I recently encountered a requirement where I needed to create a deep copy of nested Maps and Lists within a Groovy service. After some research and experimentation, I came up with a solution that worked for my use case, but I’m curious to hear your thoughts on it.

The Requirement

I had to create a deep copy of a complex data structure that included nested Maps and Lists. The goal was to ensure that modifying the copy wouldn’t affect the original data. Here’s the method I used to solve this problem:

def deepCopyCollection(object) {
    if (object instanceof Map) {
        // Recursively deep copy each entry in the map
        object.collectEntries { key, value ->
            [key, deepCopyCollection(value)]
        }
    } else if (object instanceof List) {
        // Recursively deep copy each element in the list
        object.collect { item ->
            deepCopyCollection(item)
        }
    } else {
        // For non-map, non-list values, return the value as is
        object
    }
}

An Alternate Approach

I also considered using serialization and deserialization to achieve deep copying by using Json Slurper

def newMap = new JsonSlurper().parseText(JsonOutput.toJson(OldMap))

My Questions for the Community

  1. Comparison of Approaches: Between the recursive method and the serialization-based method, which one do you think is more efficient or reliable, especially in the context of Moqui?
  2. Review Request: Could you review the recursive method I provided above? Are there any improvements or pitfalls I should be aware of?
  3. Moqui Functionality: Does Moqui provide any built-in functionality for deep copying nested Maps and Lists? If not, I would be interested in contributing this feature to the Moqui framework. Could anyone guide me on how to go about this?

Looking forward to your feedback and suggestions!

Thanks,
Nishtha

1 Like

Welcome @Nishtha-Jain and thanks for the quality post.

There is a deep copy for MNode: moqui-framework/framework/src/main/java/org/moqui/util/MNode.java at d677e40c14e7a93b10eefed245e582ae3bad6e5d · moqui/moqui-framework · GitHub

Using a Json serializer may not be the greatest idea because it is slow.

Not sure if this is helpful, but most cloning in the Moqui framework is just done with .clone( see: Code search results · GitHub

@Nishtha-Jain feel free to join the Moqui call tomorrow to talk about this though.

Thank you for the warm welcome and the helpful pointers @michael .

I’ve tried both suggestions, and here are my findings:

  1. The deepCopy method is indeed useful, but it’s mainly designed for MNode and not for maps or lists.
  2. The clone() method doesn’t seem to work for deep copying when it comes to nested structures like maps and lists.

Can we consider adding a deep copy utility for maps and lists in Moqui? What do you think?

1 Like

Yeah I’d be fine adding it in with a good use case or code contribution that requires it. Although I’m not the one who has final approval.