Different names of JSON property during serialization and deserialization

JavaJsonJackson

Java Problem Overview


Is it possible: to have one field in class, but different names for it during serialization/deserialization in Jackson library?

For example, I have class "Coordiantes".

class Coordinates{
  int red;
}

For deserialization from JSON want to have format like this:

{
  "red":12
}

But when I will serialize object, result should be like this one:

{
  "r":12
}

I tried to implement this by applying @JsonProperty annotation both on getter and setter (with different values):

class Coordiantes{
    int red;
   
    @JsonProperty("r")
    public byte getRed() {
      return red;
    }

    @JsonProperty("red")
    public void setRed(byte red) {
      this.red = red;
    }
}

but I got an exception:

>org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "red"

Java Solutions


Solution 1 - Java

Just tested and this works:

public class Coordinates {
    byte red;

    @JsonProperty("r")
    public byte getR() {
      return red;
    }

    @JsonProperty("red")
    public void setRed(byte red) {
      this.red = red;
    }
}

The idea is that method names should be different, so jackson parses it as different fields, not as one field.

Here is test code:

Coordinates c = new Coordinates();
c.setRed((byte) 5);

ObjectMapper mapper = new ObjectMapper();
System.out.println("Serialization: " + mapper.writeValueAsString(c));

Coordinates r = mapper.readValue("{\"red\":25}",Coordinates.class);
System.out.println("Deserialization: " + r.getR());

Result:

Serialization: {"r":5}
Deserialization: 25

Solution 2 - Java

You can use @jsonAlias which got introduced in jackson 2.9.0

Example:

public class Info {
  @JsonAlias({ "red" })
  public String r;
}

This uses r during serialization, but allows red as an alias during deserialization. This still allows r to be deserialized as well, though.

Solution 3 - Java

You can use a combination of @JsonSetter, and @JsonGetter to control the deserialization, and serialization of your property, respectively. This will also allow you to keep standardized getter and setter method names that correspond to your actual field name.

import com.fasterxml.jackson.annotation.JsonSetter;    
import com.fasterxml.jackson.annotation.JsonGetter;

class Coordinates {
	private int red;

	//# Used during serialization
	@JsonGetter("r")
	public int getRed() {
		return red;
	}

	//# Used during deserialization
	@JsonSetter("red")
	public void setRed(int red) {
		this.red = red;
	}
}

Solution 4 - Java

I would bind two different getters/setters pair to one variable:

class Coordinates{
    int red;

    @JsonProperty("red")
    public byte getRed() {
      return red;
    }

    public void setRed(byte red) {
      this.red = red;
    }

    @JsonProperty("r")
    public byte getR() {
      return red;
    }

    public void setR(byte red) {
      this.red = red;
    }
}

Solution 5 - Java

It's possible to have normal getter/setter pair. You just need to specify access mode in @JsonProperty

Here is unit test for that:

public class JsonPropertyTest {

  private static class TestJackson {

    private String color;

    @JsonProperty(value = "device_color", access = JsonProperty.Access.READ_ONLY)
    public String getColor() {
      return color;
    };

    @JsonProperty(value = "color", access = JsonProperty.Access.WRITE_ONLY)
    public void setColor(String color) {
      this.color = color;
    }

  }

  @Test
  public void shouldParseWithAccessModeSpecified() throws Exception {
    String colorJson = "{\"color\":\"red\"}";
    ObjectMapper mapper = new ObjectMapper();
    TestJackson colotObject = mapper.readValue(colorJson, TestJackson.class);

    String ser = mapper.writeValueAsString(colotObject);
    System.out.println("Serialized colotObject: " + ser);
  }
}

I got the output as follows:

Serialized colotObject: {"device_color":"red"}

Solution 6 - Java

You can use this variant:

import lombok.Getter;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;

//...

@JsonProperty(value = "rr") // for deserialization
@Getter(onMethod_ = {@JsonGetter(value = "r")}) // for serialization
private String rrrr;

with Lombok getter

Solution 7 - Java

This was not what I was expecting as a solution (though it is a legitimate use case). My requirement was to allow an existing buggy client (a mobile app which already released) to use alternate names.

The solution lies in providing a separate setter method like this:

@JsonSetter( "r" )
public void alternateSetRed( byte red ) {
    this.red = red;
}

Solution 8 - Java

Annotating with @JsonAlias which got introduced with Jackson 2.9+, without mentioning @JsonProperty on the item to be deserialized with more than one alias(different names for a json property) works fine.

I used com.fasterxml.jackson.annotation.JsonAlias for package consistency with com.fasterxml.jackson.databind.ObjectMapper for my use-case.

For e.g.:

@Data
@Builder
public class Chair {

    @JsonAlias({"woodenChair", "steelChair"})
    private String entityType;

}


@Test
public void test1() {
   
   String str1 = "{\"woodenChair\":\"chair made of wood\"}";
   System.out.println( mapper.readValue(str1, Chair.class));
   String str2 = "{\"steelChair\":\"chair made of steel\"}";
   System.out.println( mapper.readValue(str2, Chair.class));

}

just works fine.

Solution 9 - Java

I know its an old question but for me I got it working when I figured out that its conflicting with Gson library so if you are using Gson then use @SerializedName("name") instead of @JsonProperty("name") hope this helps

Solution 10 - Java

They must have included this as a feature, because now setting a different @JsonProperty for a getter and setter results in exactly what you would expect (different property name during serialization and deserialization for the same field). Jackson version 2.6.7

Solution 11 - Java

In my case, I had to read inputs in Brazilian portuguese and generate outputs in english.

So, a workaround which worked for me was using @JsonAlias instead of @JsonProperty:


// pseudo-java
@Value
public class User {

   String username;

   public User(
      @JsonAlias("nome_usuario") String username) {
     // ...
   }

}

Solution 12 - Java

You can write a serialize class to do that:

public class Symbol

{
	 private String symbol;

	 private String name;

     public String getSymbol() {
		return symbol;
	}
	public void setSymbol(String symbol) {
		this.symbol = symbol;
	}	 
	public String getName() {
		return name;
	}	 
	public void setName(String name) {
		this.name = name;
	}
}
public class SymbolJsonSerializer extends JsonSerializer<Symbol> {
 
	@Override
	public void serialize(Symbol symbol, JsonGenerator jgen, SerializerProvider serializers) throws IOException, JsonProcessingException {
		jgen.writeStartObject();
		
		jgen.writeStringField("symbol", symbol.getSymbol());
         //Changed name to full_name as the field name of Json string
		jgen.writeStringField("full_name", symbol.getName());
		jgen.writeEndObject(); 
	}
}

            ObjectMapper mapper = new ObjectMapper();
		
			SimpleModule module = new SimpleModule();
			module.addSerializer(Symbol.class, new SymbolJsonSerializer());
			mapper.registerModule(module); 

            //only convert non-null field, option...
			mapper.setSerializationInclusion(Include.NON_NULL); 
			 
			String jsonString = mapper.writeValueAsString(symbolList);
 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkiRachView Question on Stackoverflow
Solution 1 - JavabezmaxView Answer on Stackoverflow
Solution 2 - JavaAsuraView Answer on Stackoverflow
Solution 3 - JavaXaero DegreazView Answer on Stackoverflow
Solution 4 - JavaDRCBView Answer on Stackoverflow
Solution 5 - JavaRaman YelianevichView Answer on Stackoverflow
Solution 6 - JavaVitalii TView Answer on Stackoverflow
Solution 7 - JavaAndy TalkowskiView Answer on Stackoverflow
Solution 8 - JavaArnab DasView Answer on Stackoverflow
Solution 9 - JavaKhaledView Answer on Stackoverflow
Solution 10 - JavaJan SiekierskiView Answer on Stackoverflow
Solution 11 - JavaJaumzeraView Answer on Stackoverflow
Solution 12 - JavaVernon KujyioView Answer on Stackoverflow