Kotlin / kotlinx.serialization

Kotlin multiplatform / multi-format serialization
Apache License 2.0
5.36k stars 619 forks source link

Deep copy/clone with serialization-core #1238

Open altavir opened 3 years ago

altavir commented 3 years ago

What is your use-case and why do you need this feature? Deep copy is rarely used and is in general should be avoided. Still, there are cases, where it is needed. For example for local testing of client-server interaction.

Another case is the cloning of a subtree of a complicated mutable state graph.

Describe the solution you'd like It seems to be possible to directly clone a serializable object with the kotlinx-serialization-core directly (without any format plugins) by attaching a Decoder to the Encoder directly. The API could look like this fun <T: Any> clone(serializer: KSerializer<T>, obj: T): T.

altavir commented 3 years ago

An additional idea from @IRus is to use the same mechanics to transform objects from one type to another using different serializing for a coder and decoder.

krottv commented 3 years ago

I currently use smth like this json.encode(json.decode(obj)) But it would be nice to have a good and optimized api.

elizarov commented 3 years ago

@krottv What's your use-case? What do you use deep clone for?

krottv commented 3 years ago

@elizarov In my app I use deep clone for analytics. To send which fields are changed. This is the use case:

fun onCreate(someObject: Any) {
   val modifiedObject = someObject
   val originalObject = someObject.clone()
   modifyObject(modifiedObject)

   sendAnalyticsWhichFieldsAreChanged(originalObject, modifiedObject)
}
elizarov commented 3 years ago

@krottv I wonder what kind of approach you use to analyze what has changed? For me, the very problem of finding changes seems to be quite similar to the problem of cloning itself.

krottv commented 3 years ago

@elizarov To find changes I simply compare each field of the objects, since the type is known.

elizarov commented 3 years ago

@krottv See, any cloning library that is based on serialzaiton-core will internally consist of serialization into some internal representation and then deserialization from it. Of course, it does not have to be JSON, but something more efficient for in-memory serialization and storage. But for your use-case, you don't even need to implement a deserialization step. All you really need is to serialize the original object into some like internal format (that has keeps arrays of field names and values), then serialize updated version of it, and then you can implement your change analysis logic directly on their serialized versions. Does it make sense?

krottv commented 3 years ago

@elizarov Yes, agreed. It would be better to serialize both objects to map and then it would be even easier to find changes.