jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

JsonSerialize(Typing.DYNAMIC) in some cases does not redefine MapperFeature.USE_STATIC_TYPING

Open garkin opened this issue 7 years ago • 2 comments

As unit test output shows, annotation overrides mapper feature only for:

  • single field (annotatedValue)

And it's ignored for:

  • annotated collection (annotatedList)
  • annotated class field (dynamicValue )
  • annotated class collection (dynamicList)

This is not expected behavior (for annotated list field, at least), since MapperFeature#USE_STATIC_TYPING says that:

This global default value can be overridden at class, method or field level by using JsonSerialize.typing() annotation property.

Test bellow is written in Kotlin, sorry for that. Was tested with Jackson 2.8.6

package com.testing.jackson

import com.fasterxml.jackson.databind.MapperFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import org.junit.Test
import java.util.*
import kotlin.test.assertEquals


abstract class Base { val a = 1 }
class Derived : Base() { val b = 2 }

@JsonSerialize(typing = JsonSerialize.Typing.DYNAMIC)
abstract class BaseDynamic { val a = 1 }
class DerivedDynamic : BaseDynamic() { val b = 2 }

class Mutter {
    val value: Base = Derived()
    @JsonSerialize(typing = JsonSerialize.Typing.DYNAMIC)
    val annotatedValue: Base = Derived()
    val dynamicValue: BaseDynamic = DerivedDynamic()

    val list = ArrayList<Base>().apply { this.add(Derived()) }
    @JsonSerialize(typing = JsonSerialize.Typing.DYNAMIC)
    val annotatedList = ArrayList<Base>().apply { this.add(Derived()) }
    val dynamicList = ArrayList<BaseDynamic>().apply { this.add(DerivedDynamic()) }
}

class jackson_typing_fails {
    @Test fun go() {
        val mapper = ObjectMapper()
                .enable(MapperFeature.USE_STATIC_TYPING)
        //        .enable(SerializationFeature.INDENT_OUTPUT)
        val writer = mapper.writerFor(Mutter::class.java)
        val v = Mutter()
        val s = writer.writeValueAsString(v)
        // println(s)
        val EXPECTED = """{"value":{"a":1},"annotatedValue":{"a":1,"b":2},"dynamicValue":{"a":1,"b":2},"list":[{"a":1}],"annotatedList":[{"a":1,"b":2}],"dynamicList":[{"a":1,"b":2}]}"""
        assertEquals(EXPECTED, s)
    }
}
org.junit.ComparisonFailure: 
Expected :{"value":{"a":1},"annotatedValue":{"a":1,"b":2},"dynamicValue":{"a":1,"b":2},"list":[{"a":1}],"annotatedList":[{"a":1,"b":2}],"dynamicList":[{"a":1,"b":2}]}
Actual   :{"value":{"a":1},"annotatedValue":{"a":1,"b":2},"dynamicValue":{"a":1},"list":[{"a":1}],"annotatedList":[{"a":1}],"dynamicList":[{"a":1}]}

garkin avatar Feb 02 '17 21:02 garkin