Hey guys! I am learning about serialization and am...
# serialization
m
Hey guys! I am learning about serialization and am trying to write my own KSerializer but I have some trouble with this class:
Copy code
@Serializable(with = ObservedFolder.Companion::class)
class ObservedFolder(path: Path?, opened: Boolean, name: String) : Controller() {
  val pathProperty = SimpleObjectProperty<Path?>(path)
  var path: Path?
    get() = pathProperty.value
    set(newValue) = pathProperty.set(newValue)

  val openedProperty = SimpleBooleanProperty(opened)
  var opened: Boolean
    get() = openedProperty.value
    set(newValue) = openedProperty.set(newValue)

  val nameProperty = SimpleStringProperty(name)
  var name: String
    get() = nameProperty.value
    set(newValue) = nameProperty.set(newValue)

  fun toJson(): String {
    return JSON.encodeToString(this)
  }

  @OptIn(ExperimentalSerializationApi::class)
  companion object : KSerializer<ObservedFolder> {
    private val JSON = Json { explicitNulls = false }

    fun fromJson(json: String): ObservedFolder {
      return JSON.decodeFromString(json)
    }

    override val descriptor: SerialDescriptor = buildClassSerialDescriptor(ObservedFolder::class.simpleName!!) {
      element<String?>(ObservedFolder::path.name)
      element<Boolean>(ObservedFolder::opened.name)
      element<String>(ObservedFolder::name.name)
    }

    override fun serialize(encoder: Encoder, value: ObservedFolder) {
      encoder.encodeStructure(descriptor) {
        encodeNullableSerializableElement(descriptor, 0, serializer<String?>(), value.path?.toString())
        encodeBooleanElement(descriptor, 1, value.opened)
        encodeStringElement(descriptor, 2, value.name)
      }
    }

    override fun deserialize(decoder: Decoder): ObservedFolder {
      var path: Path? = null
      var opened = false
      var name = ""

      decoder.decodeStructure(descriptor) {
        loop@ while (true) {
          when (val i = decodeElementIndex(descriptor)) {
            CompositeDecoder.DECODE_DONE -> break@loop
            0 -> path = decodeNullableSerializableElement(descriptor, i, serializer<String?>()) ?.let { Path.of(it) }
            1 -> opened = decodeBooleanElement(descriptor, i)
            2 -> name = decodeStringElement(descriptor, i)
            else -> throw SerializationException("Unknown index $i")
          }
        }
        endStructure(descriptor)
      }

      return ObservedFolder(path, opened, name)
    }
  }
}
When I the following code:
Copy code
val json = ObservedFolder(Path.of("Observed/BlaPath.json"), false, "BlaName").toJson()
val json2 = ObservedFolder(null, true, "NullName").toJson()

println(json)
println(json2)

println(ObservedFolder.fromJson(json))
println(ObservedFolder.fromJson(json2))
I get this output:
Copy code
{"path":"Observed\\BlaPath.json","opened":false,"name":"BlaName"}
{"opened":true,"name":"NullName"}

kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 63: Expected end of the object '}', but had '"' instead
JSON input: {"path":"Observed\\BlaPath.json","opened":false,"name":"BlaName"}
...
The deserialization fails because for some reason, it is expecting the object to end at offset 63, and I don't quite understand why it's expecting that...