AutoValue Class needs @JsonProperty for all it's abstract methods
See original GitHub issueI am using Jackson version 2.9.8, because some of my libraries depend on it (Jersey 2.27
and aws-serverless-java-container-jersey 1.3.1
). I am using Jackson inside Jersey, running locally for testing under Tomcat 9, returning an AutoValue immutable object, constructed with a Builder, as the resutl of a REST GET method, encoded as JSON.
I originally defined my User
class like this:
package com.example.autojackson;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.auto.value.AutoValue;
import java.util.UUID;
@AutoValue
@JsonSerialize(as = User.class)
@JsonDeserialize(builder = AutoValue_User.Builder.class)
public abstract class User {
public abstract UUID id();
@JsonProperty("first_name")
public abstract String firstName();
@JsonProperty("last_name")
public abstract String lastName();
public abstract String cellphone();
public abstract String email();
@JsonProperty("picture_url")
public abstract String pictureUrl();
@JsonProperty("user_status")
public abstract short userStatusCode();
public abstract float rating();
public abstract String gender();
public static Builder builder() {
return new AutoValue_User.Builder();
}
public abstract Builder toBuilder();
@AutoValue.Builder
@JsonPOJOBuilder(withPrefix = "set")
public abstract static class Builder {
public abstract Builder setId(UUID id);
@JsonProperty("first_name")
public abstract Builder setFirstName(String firstName);
@JsonProperty("last_name")
public abstract Builder setLastName(String lastName);
public abstract Builder setCellphone(String cellphone);
public abstract Builder setEmail(String email);
@JsonProperty("picture_url")
public abstract Builder setPictureUrl(String pictureUrl);
@JsonProperty("user_status")
public abstract Builder setUserStatusCode(short userStatusCode);
public abstract Builder setRating(float rating);
public abstract Builder setGender(String gender);
public abstract User build();
}
}
As you can see, only the properties with names different from the abstract method names were annotated with @JsonProperty
. According to all the docs I read, this should work, but the JSON returned to the client missed all the properties without the @JsonProperty
annotation.
If in turn I change my User
class to this one:
package com.example.autojackson;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.auto.value.AutoValue;
import java.util.UUID;
@AutoValue
@JsonSerialize(as = User.class)
@JsonDeserialize(builder = AutoValue_User.Builder.class)
public abstract class User {
@JsonProperty("id") public abstract UUID id();
@JsonProperty("first_name") public abstract String firstName();
@JsonProperty("last_name") public abstract String lastName();
@JsonProperty("cellphone") public abstract String cellphone();
@JsonProperty("email") public abstract String email();
@JsonProperty("picture_url") public abstract String pictureUrl();
@JsonProperty("user_status") public abstract short userStatusCode();
@JsonProperty("rating") public abstract float rating();
@JsonProperty("gender") public abstract String gender();
public static Builder builder() {
return new AutoValue_User.Builder();
}
public abstract Builder toBuilder();
@AutoValue.Builder
@JsonPOJOBuilder(withPrefix = "set")
public abstract static class Builder {
@JsonProperty("id") public abstract Builder setId(UUID id);
@JsonProperty("first_name") public abstract Builder setFirstName(String firstName);
@JsonProperty("last_name") public abstract Builder setLastName(String lastName);
@JsonProperty("cellphone") public abstract Builder setCellphone(String cellphone);
@JsonProperty("email") public abstract Builder setEmail(String email);
@JsonProperty("picture_url") public abstract Builder setPictureUrl(String pictureUrl);
@JsonProperty("user_status") public abstract Builder setUserStatusCode(short userStatusCode);
@JsonProperty("rating") public abstract Builder setRating(float rating);
@JsonProperty("gender") public abstract Builder setGender(String gender);
public abstract User build();
}
}
The JSON returned by the REST endpoint correctly includes all the AutoValue implemented properties of this value class, but it’s tedious and error prone to be setting all the @JsonProperty
annotations.
If you can’t reproduce this, for any reasons, please do let me know and I will upload a fully functioning Jersey example.
I could reproduce this by running:
public void testJacksonAutoValue() {
User user = User.builder()
.setId(UUID.randomUUID())
.setFirstName("John")
.setLastName("Smith")
.setCellphone("99999")
.setEmail("jhon@smith.com")
.setPictureUrl("http://www.test.com")
.setUserStatusCode((short) 1)
.setRating((float) 5.0)
.setGender("m")
.build();
ObjectMapper mapper = new ObjectMapper();
try {
System.out.println(mapper.writeValueAsString(user));
} catch (Exception e) {
e.printStackTrace();
}
}
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:9 (5 by maintainers)
Thank you for reporting this.
I see, well, thanks for your time, I filed another issue with a Feature Request.