question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AutoValue Class needs @JsonProperty for all it's abstract methods

See original GitHub issue

I 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:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
cowtowncodercommented, Jun 4, 2019

Thank you for reporting this.

0reactions
feinsteincommented, Mar 31, 2020

I see, well, thanks for your time, I filed another issue with a Feature Request.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Learn AutoValue and Jackson - enid0227 Learning Notes
“AutoValue is a great tool for eliminating the drudgery of writing mundane value classes in Java. It encapsulates much of the advice in ......
Read more >
Use Auto Value and Jackson in REST API - Mincong Huang
It shares how to apply Jackson annotations on top of Auto Value . ... and continue with the class name of the abstract...
Read more >
Jackson + Autovalue Builder bean validation - Stack Overflow
I have a the following Event DTO class: @AutoValue @JsonDeserialize(builder = AutoValue_Event.
Read more >
Introduction to AutoValue - Baeldung
In order to generate a value-type object all you have to do is to annotate an abstract class with the @AutoValue annotation and...
Read more >
com.google.auto.value.AutoValue.<init> java code examples
@JsonAutoDetect @AutoValue public abstract class ContentPackResponse { @JsonProperty("content_pack") public abstract ContentPack contentPack(); ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found