https://kotlinlang.org logo
#jackson-kotlin
Title
# jackson-kotlin
d

Dariusz Kuc

05/21/2021, 9:49 PM
hello 👋 by any chance anyone tried conditional serialization of fields based on some condition? (I tried using custom filter as was suggested here -> https://www.baeldung.com/jackson-serialize-field-custom-criteria but with no luck). See thread for code
Copy code
sealed class OptionalInput<out T> {
    /**
     * Represents missing/undefined value.
     */
    object Undefined : OptionalInput<Nothing>() {
        override fun toString() = "UNDEFINED"
    }

    /**
     * Wrapper holding explicitly specified value including NULL.
     */
    class Defined<out U> @JsonCreator constructor(@JsonValue val value: U?) : OptionalInput<U>() {
        override fun toString(): String = "Defined(value=$value)"
    }
}

@JsonFilter(value = "optionalInputFilter")
data class InputObject(
    val name: OptionalInput<String>,
    val value: OptionalInput<Int>
)

class OptionalInputFilter : SimpleBeanPropertyFilter() {
    override fun serializeAsField(
        pojo: Any?,
        jgen: JsonGenerator,
        provider: SerializerProvider,
        writer: PropertyWriter
    ) {
        if (pojo is OptionalInput.Undefined) { // pojo is an instance of InputObject, this does not get invoked for fields
            writer.serializeAsOmittedField(pojo, jgen, provider)
        } else {
            writer.serializeAsField(pojo, jgen, provider)
        }
    }
}

val mapper = jacksonObjectMapper()
val filters = SimpleFilterProvider().addFilter("optionalInputFilter", OptionalInputFilter())

val notSpecified = InputObject(name = OptionalInput.Defined("123"), value = OptionalInput.Undefined)
println("not specified: ${mapper.writer(filters).writeValueAsString(notSpecified)}"). // prints out: not specified: {"name":"123","value":{}}
if I use custom serializer instead
Copy code
override fun serialize(value: OptionalInput<*>, gen: JsonGenerator, serializers: SerializerProvider) {
    when (value) {
        is OptionalInput.Undefined -> return
        is OptionalInput.Defined -> {
            if (value.value == null) {
                serializers.defaultNullValueSerializer.serialize(value.value, gen, serializers)
            } else {
                serializers.findValueSerializer(value.value::class.java).serialize(value.value, gen, serializers)
            }
        }
    }
}
I end up with invalid
{ "name": "123", "value" }
if anyone else is looking for solution, custom serializer works fine when you set serialization policy to omit empty
Copy code
val mapper = jacksonObjectMapper()
mapper.setSerializationInclusion(Include.NON_EMPTY)
21 Views