Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop Jackson from changing case of variable names

I am using Jackson in Spring to serialize my class to JSON. When I serialize a class like the example below, Jackson is changing the names of certain fields from Camel Case to lower case. I know I can work around this by creating custom (de)serializers, yet I am hoping to turn this off globally. Perhaps by setting a property in application.properties.

Per the default Jackson naming strategy, this is not supposed to happen:

In absence of a registered custom strategy, default Java property naming strategy is used, which leaves field names as is...

class Foo {
    private final String firstName;
    private final String aName;
    private final String name;
    private final String abName;

    Foo(final String firstName, final String aName, final String name, final String abName) {
        this.firstName = firstName;
        this.aName = aName;
        this.name = name;
        this.abName = abName;
    }
    // Getters here
}

public static void main(String[] args) {
        final ObjectMapper mapper = new ObjectMapper();
        final Foo foo  = new Foo("first", "a", "name", "ab");
        final String jsonInString = mapper.writeValueAsString(foo);
        System.out.println(jsonInString);
}

Expected:

{"firstName":"first","name":"name","abName":"ab","aName":"a"}

Actual:

{"firstName":"first","name":"name","abName":"ab","aname":"a"}

EDIT:

Narrowed the problem down to interpretation of the getters. Starting to look like a bug in Jackson.

class Foo {
    private final String aName;

    Foo(final String aName) {
        this.aName = aName;
    }

    public String getaName() {
        return this.aName;
    }
}

Serializes to {"aName":"a"}

However,

class Foo {
    private final String aName;

    Foo(final String aName) {
        this.aName = aName;
    }

    public String getAName() {
        return this.aName;
    }
}

Serializes to {"aname":"a"}

like image 760
AnthonyW Avatar asked Oct 09 '17 17:10

AnthonyW


3 Answers

The problem here is more about JavaBeans(TM) Specification. According to the spec (page 58)

However to support the occasional use of all upper-case names, we check if the first two characters of the name are both upper case and if so leave it alone

“FooBah” becomes “fooBah”

“Z” becomes “z”

“URL” becomes “URL”

And you have an edge case with aName field . Because if the getter looks like AName() , then when you convert back from this getter you should look for AName field according to the specification. Here is additional info explanation

So to fix this, you can use a proper getter(getaName()) or @JsonProperty("aName") annotation above field/getter

Here is similar question

like image 139
varren Avatar answered Oct 26 '22 21:10

varren


Although I'm not sure why Jackson reads getAName to aname, it's possible to force a Jackson to use a certain name with @JsonProperty("AName"). For example:

class Foo {
    private final String aName;

    Foo(final String aName) {
        this.aName = aName;
    }

    @JsonProperty("AName")
    public String getAName() {
        return this.aName;
    }
}

(Got this solution from this closely related question.)

like image 5
user70585 Avatar answered Oct 26 '22 20:10

user70585


You can also use PropertyNamingStrategy option in Objectmapper.

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE)
like image 1
Shashwat Kumar Avatar answered Oct 26 '22 19:10

Shashwat Kumar