JsonIgnore for Scala method with default parameters does not work as expected

Viewed 29

I would like to mark the default method generated by scala compiler to be ignored from being serialized.

@JsonIgnore def getSum(a: Int, b: Int = 2): Int = a + b

compiler creates two methods:

def getSum(a: Int, b: Int): Int = a.+(b);

<synthetic> def getSum$default$2(): Int = 2; (default value at position 2)

The first method getSum does not get serialized as the JsonIgnore is applied on it, but the new default parm method generated is serialized by jackson, how to tell Jackson to not serialize it?

Example:

  import com.fasterxml.jackson.annotation.JsonIgnore
  import com.fasterxml.jackson.databind.ObjectMapper;

  case class A(id: Int) {
    @JsonIgnore def getSum(a: Int, b: Int = 2): Int = a + b
  }

  @Test
  def test(): Unit = {
    val a = A(5)
    val mapper = new ObjectMapper()
    println(mapper.writeValueAsString(a))
  }

output: {"id":5,"sum$default$2":2}

1 Answers

I believe this is a bug, but there are workarounds:

Explicitly ignore the generated property

The @JsonIgnoreProperties annotation can be used at the class level.

@JsonIgnoreProperties(Array("sum$default$2"))
case class A(id: Int) {
  def getSum(a: Int, b: Int = 2): Int = a + b
}

Rename the method

It's detected as a property because it matches the JavaBeans getter convention. If the method name can be changed to remove the get prefix, it won't be treated as a property by Jackson:

case class A(id: Int) {
  def calculateSum(a: Int, b: Int = 2): Int = a + b
}

Avoid default arguments

Of course, another option is to avoid the use of default arguments entirely in favour of method overloading:

case class A(id: Int) {
  def getSum(a: Int, b: Int): Int = a + b
  def getSum(a: Int): Int = getSum(a, 2)
}

These examples are all demonstrated in this Scastie: https://scastie.scala-lang.org/TimMoore/werEmJF9S7ip4QP5sT73CQ/39

All of these options produce this JSON:

{"id":5}
Related