Sometimes, you don't want to stay consistent.

There are occasions when you want to use Jackson to deserialize a JSON object to a Java object but you want to map one of the JSON properties to a Java field with a different name.

Or... you might want to serialize a Java object to a JSON object but you want to map one of the Java fields to a JSON property with a different name.

It's happened to all of us.

And in this guide, I'll show you multiple ways to handle that situation.

The Easiest Way

I like this first way the best because it works for both serialization and deserialization. The other methods only work in one direction.

By the way: all three of these methods make use of Jackson annotations. We're not going to go fancy here with our own custom serialization/deserialization code. 

Anyhoo, let's start with @JsonProperty.

Just plop that thing right on top of the Java field you want to map to a different JSON property.

But.. you also need to specify the name of the JSON property in parentheses next to the annotation.

Let's look at an example. Here's a simple Employee class that just defines the employee ID and name:

public class Employee {

    private String id;
    
    @JsonProperty("EmployeeName")
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
}

That's a plain old Java object (POJO). You've probably seen plenty like that before.

But note that the name property uses the @JsonProperty annotation. And in parentheses next to it, you'll see the word "EmployeeName" in quotation marks.

That means the name field in the Java object maps to the "EmployeeName" property in the JSON object.

Let's write a little code to see it in action:

ObjectMapper mapper = new ObjectMapper();            

Employee employee = new Employee();
employee.setId("A17");
employee.setName("Frank");

System.err.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee));

That code gets the ball rolling by instantiating an ObjectMapper object that's used to serialize and deserialize.

Then, it instantiates an Employee object and sets the only two fields available: id and name.

Finally it serializes the Employee object and spits out the JSON representation in pretty red letters because I like red letters.

Here's what it looks like:

{
  "id" : "A17",
  "EmployeeName" : "Frank"
}

You see that? The "id" property stayed the same but the "EmployeeName" property reflects the name property in the Java class.

Which is exactly the expected behavior.

Now let's see the whole thing in reverse.

ObjectMapper mapper = new ObjectMapper();  
            
String json = "{\r\n"
        + "  \"id\" : \"A17\",\r\n"
        + "  \"EmployeeName\" : \"Frank\"\r\n"
        + "}";
            
Employee employee = mapper.readerFor(Employee.class).readValue(json);
System.err.println(employee);

Once again, the code kicks off by instantiating our good friend ObjectMapper.

Then it creates a String object that looks exactly like that JSON output you saw above.

Next, the code uses the ObjectMapper instance to deserialize the JSON string.

Finally, it prints out the Java Employee object that got created by the mapper. And it looks something like this:

Employee@3e2e18f2[id=A17,name=Frank]

And that's exactly what you'd expect because the code mapped "EmployeeName" on the JSON side to the name field on the Java side.

That's one way to handle this.

The Alias Way

You could also use @JsonAlias.

It's pretty straightforward. Just put the alias name or names in curly braces, separated by commas.

...
    @JsonAlias({"employeeName"})
    private String name;
...

Take out all the other annotations from the Employee class.

Then, run this code:

ObjectMapper mapper = new ObjectMapper();  
            
String json = "{\r\n"
        + "  \"id\" : \"A17\",\r\n"
        + "  \"employeeName\" : \"Frank\"\r\n"
        + "}";
            
Employee employee = mapper.readerFor(Employee.class).readValue(json);
System.err.println(employee);

And you should see output that looks like this:

playground.Employee@61230f6a[id=A17,name=Frank]

See what Jackson did there?

It mapped the JSON property "employeeName" to the Java field name. That's because @JsonAlias defined "employeeName" as an alias for that field.

Serialization With @JsonGetter

I did some searching online and noticed that a couple of folks aren't explaining this one accurately. So I guess it's up to me.

If you want to serialize your Java object and map a field name in Java to a different property name in JSON, you can use @JsonGetter

Let's see it in practice:

public class Employee {

    private String id;    
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @JsonGetter("name")
    public String getEmployeeName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
}

Note that there's no @JsonProperty annotation. Also there's no getName() method.

Instead, there's a getEmployeeName() method that's annotated with @JsonGetter("name").

That tells Jackson to map the return value of that method to a JSON property called "name" during the serialization process. 

Now run this code again:

ObjectMapper mapper = new ObjectMapper();            

Employee employee = new Employee();
employee.setId("A17");
employee.setName("Frank");

System.err.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee));

And you'll get this output:

{
  "id" : "A17",
  "name" : "Frank"
}

Boom. Even though there's no getter for name, you still created a JSON object with a "name" property.

Deserialization With @JsonSetter

And this one should be fairly easy for you to figure out.

Change the Employee class to this:

public class Employee {

    private String id;    
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    @JsonSetter("EmployeeName")
    public void setName(String name) {
        this.name = name;
    }
    
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
}

Note that the @JsonGetter method is gone and instead the setName() method is annotated with @JsonSetter("EmployeeName").

That tells Jackson to use that method when deserializing the JSON object's "EmployeeName" property. Effectively it sets the JSON "EmployeeName" value to the value of the Java name field.

Now run this code again:

ObjectMapper mapper = new ObjectMapper();  
            
String json = "{\r\n"
        + "  \"id\" : \"A17\",\r\n"
        + "  \"EmployeeName\" : \"Frank\"\r\n"
        + "}";
            
Employee employee = mapper.readerFor(Employee.class).readValue(json);
System.err.println(employee);

And you'll get this output:

playground.Employee@418e7838[id=A17,name=Frank]

Exactly what you're looking for. The name field is set to the same value as the "EmployeeName" property in the JSON object.

Wrapping It Up

There you have it. A few ways to map fields of different names when using Jackson to serialize and deserialize objects.

Pick the option that you think works best for your use case and run with it.

Have fun!

Brian Babb on Unsplash