Kotlinx.serialization - serialize/apply only changes

Is there a way to serialize only the changes made on an instance and then apply the changes on another instance, assuming the starting point of the two instances are the same?

Something like this:

class Data(var value : Int)

val dataA = Data(1)
val dataB = Data(1)

dataA.value = 12

// here patch should be something I can send over the network, save to file, etc.
val patch = dataA.getPatch()

dataB.patch(patch)

assertEquals(12, dataB.value)
1 Like

I think the issue is not strictly related to kotlinx.serialization per se. What you need is a library for comparing/auditing 2 objects and then applying those diffs to another objects.

1 Like

You are partially right, but:

  • I want to send the patches through the network/store them and then serialization comes into play.
  • My project uses kotlinx.serialization, so it would be the best to build on it.
  • I feel the right way to do this is by a compiler plugin which brings kotlinx.serialization into the picture yet again as it is a compiler plugin which does almost what I want.
  • It does matter if I have to write the bridge between the “comparing/auditing” library and the serialization library. I would like to avoid that.
  • Comparing objects is a very different approach, I would like to avoid that also. Auditing is better if we talk about a change list. However, that change list should be serializable with my standard tools (i.e. multiplatform).

My original post is to get information before I decide which way I go. For example, if there are plans to add something like this to kotlinx.serialization I wouldn’t spend time on this issue.

If there is a multiplatform auditing library which works with Kotlin objects without much boilerplate I would be happy to use it, please point me to the right direction.

I guess you could use kotlinx.serialization.properties
Encoding would look like:

  1. Encode dataA and dataB object to map (mapA and mapB respectively)
  2. Create a map (mapC) from mapA, but with every entry that's matching in mapBremoved (I think the simples way to do this would beval mapC = mapA.entries.minus(mapB.entries).associate { it.toPair() }`)
  3. Serialize map using kotlinx.serizalization.cbor (or json)

And decoding would look like:

  1. Decode map using kotlinx.serizalization.cbor (or json)
  2. Encode unchanged object (that should have the same state as object dataB, so I’ll reuse the name) to map mapB
  3. Add mapA and mapB
  4. Decode the result

You’ll unfortunately have a separate object, but that’s as close to what you want as I can get

1 Like

Hm, interesting idea. I haven’t known of kotlinx.serialization.properties, thanks for bringing it up.

The map based solution could work but I think performance would suffer.

That said, it might point to the right direction. Maybe I can hack out the part that encodes/decodes one specific property and call it only on the ones I need. Very interesting.