question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Delegate to default Serializer

See original GitHub issue

Hi,

I’m dealing with an annoying JSON service which is out of my control.
If a value is unavailable it is expressed as an empty array [] instead of a canonical absence or null value.

I thought about making a custom JSON deserialiser and manually check if the value was present or not before delegating it to the default generated deserialiser. However when defining a custom deserialiser it seems the generated deserialiser is not generated no more.

I made a simple test case here:

public object SomeObjSerializer : KSerializer<SomeObj> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("SomeObj")

    override fun serialize(encoder: Encoder, value: SomeObj) {}

    override fun deserialize(decoder: Decoder): SomeObj {
        val input = decoder as JsonDecoder
        val jsonObj = input.decodeJsonElement().jsonObject
        return if (jsonObj["value"] is JsonPrimitive) {
            //How to delegate to the default generated serializer?
        } else {
            SomeObj(null)
        }
    }
}

@Serializable(with = SomeObjSerializer::class)
public data class SomeObj(val value: String?)

public fun main() {
    //language=JSON
    val someJson = """{"value" : [] }"""
    val clazz = Json.decodeFromString<SomeObj>(someJson)
    
    //language=JSON
    val someOtherJson = """{"value" : "42" }"""
    val clazz2 = Json.decodeFromString<SomeObj>(someOtherJson)
}

Note that this example is a simple use case.

As a temporary solution I made a copy of my object without specifying the custom deserialiser which I reference in my own deserialiser and then map back to my original object.
However that of course does not seem to be a good solution.

public object SomeObjSerializer : KSerializer<SomeObj> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("SomeObj")

    override fun serialize(encoder: Encoder, value: SomeObj) {}

    override fun deserialize(decoder: Decoder): SomeObj {
        val input = decoder as JsonDecoder
        val jsonObj = input.decodeJsonElement().jsonObject
        return if (jsonObj["value"] is JsonPrimitive) {
            val obj = decoder.decodeSerializableValue(CopyOfSomeObjForDelegationPurposedOnly.serializer())
            SomeObj(obj.value)
        } else {
            SomeObj(null)
        }
    }
}

@Serializable(with = SomeObjSerializer::class)
public data class SomeObj(val value: String?)
@Serializable
public data class CopyOfSomeObjForDelegationPurposedOnly(val value: String)

public fun main() {
    //language=JSON
    val someJson = """{"value" : [] }"""
    val clazz = Json.decodeFromString<SomeObj>(someJson)

    //language=JSON
    val someOtherJson = """{"value" : "42" }"""
    val clazz2 = Json.decodeFromString<SomeObj>(someOtherJson)
}

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:4
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
sandwwraithcommented, May 4, 2022

I think nullable JsonTransformingSerializer is a separate issue, can you please create one?

2reactions
shanshincommented, Jan 14, 2021

Unfortunately, JsonTransformingSerializer does not currently support nullable types (you can’t write something like JsonTransformingSerializer<Program?>(Program.serializer().nullable).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Calling Default Serializer from Custom Serializer in Jackson
Another way of calling the default serializers is to use the SerializerProvider. Therefore, we delegate the process to the default serializer of ...
Read more >
java - How to delegate to default deserialization in custom ...
Suppose I am writing custom serialization for some class, but would like to process one of its field with default methods. How to...
Read more >
SerializationDelegate (Spring Framework 6.0.0 API)
Create a SerializationDelegate with a default serializer/deserializer for the given ClassLoader . SerializationDelegate(Serializer<Object> serializer, ...
Read more >
How to access default serializer when writing custom serialiser
The main method for doing this is bit indirect: you need to register BeanSerializerModifier, and in method `modifySerializer(.
Read more >
StdDelegatingSerializer (jackson-databind 2.5.0 API)
Serializer implementation where given Java type is first converted to an intermediate "delegate type" (using a configured Converter , and then this delegate...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found