Skip to content

Ensure Constructor Parameter annotations are linked with those of Field, Getter, or Setter #792

@christophercurrie

Description

@christophercurrie

This issue relates to FasterXML/jackson-module-scala#197.

In Scala, the normal syntax for declaring a class takes a simplified form:

class Foo(bar: String)

This generates a JVM class that is similar to the following in Java

class Foo {
  private final String bar;

  private Foo(String bar) {
    this.bar = bar;
  }

  public getBar() {
    return bar;
  }
}

Where things get tricky is in specifying annotations on fields. To rename a property, for example, the natural syntax would look like:

class Foo(@JsonProperty("renamed") bar: String)

But the JVM that results from this looks like the following Java equivalent:

class Foo {
  private final String bar;

  private Foo(@JsonProperty("renamed") String bar) {
    this.bar = bar;
  }

  public getBar() {
    return bar;
  }
}

The getter is not tagged with the new name, and so the renaming doesn't happen on serialization. Similar issues exist for other annotations or other uses of @JsonProperty (such as exposing private fields)

The issue can be worked around in Scala by changing the way the annotation is specified on the class:

class Foo(@(JsonProperty @field @getter @setter)("renamed") bar: String)

This example is deliberately extra verbose, because even though the annotation does not need to be present in all of those locations in all cases, figuring out which ones it's needed for is a pain for Scala users.

An alternate workaround would be to create type aliases in Scala that do the same thing:

object ScalaModule {
  type JsonProperty = com.fasterxml.jackson.databind.JsonProperty @field @getter @setter
}

This is slightly better for the end user, though still not ideal, and the set of annotations would need to be kept in sync with the databind library.

The ideal solution would be a way for the Scala module to signal to databind that the annotation for the constructor parameter is significant in other locations as well. Currently this is done using faking it in findNameForSerialization, but that's not a general solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions