I have this JSON to deserialize:
{ "first-name": "Alpha", "last-name": "Beta", "gender": "m" }
I want to serialize it to 2 different formats:
[A]
{ "first-name": "Alpha", "last-name": "Beta", "gender": "m" }
[B]
{ "firstName": "Alpha", "lastName": "Beta", "gender": "m" }
I’m able to serialize it to 1 format: [A] only or [B] only. Here’s my code to serialize it to [B]:
public String firstName; public String lastName; public String gender; @JsonProperty("firstName") public String getFirstNameCC() { return firstName; } @JsonProperty("first-name") public void setFirstNameD(String firstName) { this.firstName = firstName; } @JsonProperty("lastName") public String getLastNameCC() { return lastName; } @JsonProperty("last-name") public void setLastNameD(String lastName) { this.lastName = lastName; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; }
I read about JsonView
here http://www.baeldung.com/jackson-json-view-annotation (section ‘5. Customize JSON Views’) but it only changes its value. I want to change field name as example above. Can anyone give insight on this?
Advertisement
Answer
I am not sure I completly understand your question, but for what I could understand you can do something like this to achieve different serializtions.
Create a custom annotation to hold all possible different serialization options:
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface CustomJsonProperty { String propertyName(); String format(); @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented @interface List { CustomJsonProperty[] value(); } }
Annotate your class accordingly:
@JsonSerialize(using = CustomJsonPropertySerializer.class) public class Bar { @CustomJsonProperty.List({ @CustomJsonProperty(propertyName = "first-name", format = "A"), @CustomJsonProperty(propertyName = "firstName", format = "B") }) private String firstName; @CustomJsonProperty.List({ @CustomJsonProperty(propertyName = "last-name", format = "A"), @CustomJsonProperty(propertyName = "lastName", format = "B") }) private String lastName; @CustomJsonProperty.List({ @CustomJsonProperty(propertyName = "gender-x", format = "A"), @CustomJsonProperty(propertyName = "gender", format = "B") }) private String gender; @JsonIgnore private String format; //getters & setters }
Create a custom serializer to interpret your new annotation:
public class CustomJsonPropertySerializer extends JsonSerializer<Bar> { @Override public void serialize(Bar bar, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); Field[] fields = bar.getClass().getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); Object value = null; try { value = field.get(bar); } catch (IllegalAccessException e) { e.printStackTrace(); } if (field.isAnnotationPresent(CustomJsonProperty.List.class)) { CustomJsonProperty[] properties = field.getAnnotation(CustomJsonProperty.List.class).value(); CustomJsonProperty chosenProperty = null; for (CustomJsonProperty c : properties) { if (c.format().equalsIgnoreCase(bar.getFormat())) { chosenProperty = c; break; } } if (chosenProperty == null) { //invalid format given, use first format then chosenProperty = properties[0]; } jsonGenerator.writeStringField(chosenProperty.propertyName(), value.toString()); } } jsonGenerator.writeEndObject(); } }
Now you can serialize your objects taking into consideration different formats for the property names:
public static void main(String[] args) throws IOException { Bar bar1 = new Bar("first", "last", "m", "A"); Bar bar2 = new Bar("first", "last", "m", "B"); ObjectMapper mapper = new ObjectMapper(); String json1 = mapper.writeValueAsString(bar1); String json2 = mapper.writeValueAsString(bar2); System.out.println(json1); System.out.println(json2); }
Output:
{"first-name":"first","last-name":"last","gender-x":"m"} {"firstName":"first","lastName":"last","gender":"m"}
Of course the above serializer only works for Bar objects, but that can easily be solved using inheritance with abstract String getFormat();
on the super class and changing the custom serializer to accept the super class type, instead of Bar.
Maybe there is a simpler way than creating your own stuff, but I don’t know about it. Let me know if something wasn’t clear and I can elaborate it again.