Skip to content

Commit 033761a

Browse files
committed
Fix bean accessors being used for field names
When using `@JsonProperty` on a bean property (i.e. a field with accessor methods), if you do not specify an explicit name for the property, the `ScalaAnnotationIntrospector` was incorrectly generating properties for the accessor methods. In the following example: ``` class Bean { private var value: Int = 0 @JsonProperty def getValue: Int = value @JsonProperty def setValue(value: Int): Unit = { this.value = value } } ``` A mapper configured with the `ScalaAnnotationIntrospector` would serialize this to: ``` {"value":0,"getValue":0} ``` This most notably impacts interop with Java-defined classes, as they often follow the pattern of Java Beans, where the accessor methods are annotated with `@JsonProperty`. Credit for the fix goes to @clintmiller1 (FasterXML#224 (comment)). I've included a test that verifies the problem, and the solution.
1 parent 2b34651 commit 033761a

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

src/main/scala/com/fasterxml/jackson/module/scala/introspect/BeanIntrospector.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ object BeanIntrospector {
194194
if findField(cls, name).isEmpty
195195
if !name.contains('$')
196196
if !fields.exists(_.name == name)
197-
setter = findSetter(cls, name) if setter.isDefined || getter.getAnnotation(classOf[JsonProperty]) != null
197+
getterProperty = getter.getAnnotation(classOf[JsonProperty])
198+
setter = findSetter(cls, name) if setter.isDefined || (getterProperty != null && getterProperty.value != JsonProperty.USE_DEFAULT_NAME)
198199
beanGetter = findBeanGetter(cls, name)
199200
beanSetter = findBeanSetter(cls, name)
200201
} yield PropertyDescriptor(name, None, None, Some(getter), setter, beanGetter, beanSetter)

src/test/scala/com/fasterxml/jackson/module/scala/introspect/ScalaAnnotationIntrospectorTest.scala

+13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.fasterxml.jackson
22
package module.scala
33
package introspect
44

5+
import com.fasterxml.jackson.annotation.JsonProperty
56
import com.fasterxml.jackson.core.JsonGenerator
67
import com.fasterxml.jackson.databind
78
import com.fasterxml.jackson.databind.module.SimpleModule
@@ -24,6 +25,11 @@ object ScalaAnnotationIntrospectorTest
2425
class BeanPropertyClass(@BeanProperty val param: Int)
2526
class AnnotatedBasicPropertyClass(@JsonScalaTestAnnotation val param: Token)
2627
class AnnotatedBeanPropertyClass(@JsonScalaTestAnnotation @BeanProperty val param: Token)
28+
class JavaBeanPropertyClass {
29+
private var value: Int = 0
30+
@JsonProperty def getValue: Int = value
31+
@JsonProperty def setValue(value: Int): Unit = { this.value = value }
32+
}
2733
}
2834

2935
@RunWith(classOf[JUnitRunner])
@@ -118,6 +124,13 @@ class ScalaAnnotationIntrospectorTest extends fixture.FlatSpec with Matchers {
118124
mapper.writeValueAsString(bean)
119125
}
120126

127+
it should "correctly infer name(s) of un-named bean properties" in { mapper =>
128+
val tree = mapper.valueToTree[databind.node.ObjectNode](new JavaBeanPropertyClass)
129+
tree.has("value") shouldBe true
130+
tree.has("setValue") shouldBe false
131+
tree.has("getValue") shouldBe false
132+
}
133+
121134
private def getProps(mapper: ObjectMapper, bean: AnyRef) = {
122135
val config = mapper.getSerializationConfig
123136
val beanDescription: BeanDescription = config.introspect(mapper.constructType(bean.getClass))

0 commit comments

Comments
 (0)