Different names of JSON property during serialization and deserialization
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
How to use different JSONProperty on Serialize & Deserialize using Jackson API?
Googling around i have found solution for it.
We can use @JsonAlias
using latest Jackson API (2.9.7)
So in my case i wanted this alias for deserialization @JsonAlias(value={"author","authorList"})
.
JSON Jackson parse different keys into same field
Different serialization/deserialization names with java jackson
You're on the right track. Here's an example of this working with a test JSON document.
public static class MyClass {
private String defaultReference;
@JsonProperty(value = "default_reference")
public void setDefaultReference(String defaultReference) {
this.defaultReference = defaultReference;
}
@JsonProperty(value = "defaultReference")
public String getDefaultReference() {
return defaultReference;
}
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
MyClass instance = objectMapper.readValue("{\"default_reference\": \"value\"}", MyClass.class);
objectMapper.writeValue(System.out, instance);
// Output: {"defaultReference":"value"}
}
}
Jackson: Serialize/deserialize with different property name
Try using a different JsonProperty
annotation for the getter and the setter. E.g.
@JsonProperty("tagnameOpc")
void setTagName(String name)
@JsonProperty("tagName")
String getTagName()
If that doesn't work try with an extra setter
@JsonIgnore
void setTagName(String name)
@JsonProperty("tagnameOpc")
void setTagNameOpc(String name) {
setTagName(name);
}
@JsonProperty("tagName")
String getTagName()
Different @JsonProperty config for READ and WRITE on same field?
You could use the getters and setters to get that extra customization. The get will act as READ and the set as WRITE. Note that you don't need the access properties or the field level annotation:
public abstract class StandingMixIn {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
Integer positionNumber;
// No annotation on the field
String positionText;
@JsonProperty(value = "positionText")
public String getPositionText() {
return positionText;
}
@JsonProperty(value = "position")
public void setPositionText(String positionText) {
this.positionText = positionText;
}
}
JSON Jackson parse different keys into same field
Well, as only deserialization is your concern, @JsonAlias
introduced in 2.9
is perfect for this situation. You can do something like this:
@JsonAlias({"cover_asset", "asset"})
private Asset asset;
@JsonAlias
docs:
Annotation that can be used to define one or more alternative names
for a property, accepted during deserialization as alternative to the
official name. Alias information is also exposed during POJO
introspection, but has no effect during serialization where primary
name is always used.
Note: Make sure you update all related dependencies(annotations
, core
, databind
) if you are using them. Updating just annotations
without others threw me runtime error.
Specifying different JSON property names according to API version with Jackson
You can create a custom annotation to define a list of possible version of property name for a field and create a custom JacksonAnnotationIntrospector
to resolve the property name according to a given version.
The custom annotation will look likes:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface VersioningProperties {
Property[] value();
@interface Property {
String version();
String value();
}
}
and the custom JacksonAnnotationIntrospector
will look like:
public class VersioningPropertiesIntrospector {
private String version;
public VersioningPropertiesIntrospector(String version) {
this.version = version;
}
@Override
pubilc PropertyName findNameForSerialization(Annotated a) {
PropertyName propertyName = findNameFromVersioningProperties(a);
if (propertyName != null) {
return propertyName;
}
return super.findNameForSerialization(a);
}
@Override
pubilc PropertyName findNameForDeserialization(Annotated a) {
PropertyName propertyName = findNameFromVersioningProperties(a);
if (propertyName != null) {
return propertyName;
}
return super.findNameForDeserialization(a);
}
private PropertyName findNameFromVersioningProperties(Annotated a) {
VersioningProperties annotation = a.getAnnotation(VersioningProperties.class);
if (annotation == null) {
return null;
}
for (Property property : annotation.value()) {
if (version.equals(property.version()) {
return new PropertyName(property.value());
}
}
return null;
}
}
Example of using the annotation:
public class User {
@VersioningProperties({
@Property(version = "1.5", value = "fname"),
@Property(version = "1.6", value = "firstName")
})
private String firstName;
// constructors, getters and setters
}
and an example of using ObjectMapper
with the introspector:
User user = new User();
user.setFirstName("catherine");
user.setVersion("1.5");
ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new VersioningPropertiesIntrospector(user.getVersion()));
String userJson = mapper.writeValueAsString(user);
User userRead = mapper.readValue(userJson, User.class);
You may also consider implement a factory to get ObjectMapper
by passing the version information.
Jackson Serialize Field to Different Name
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.
Related Topics
Classcastexception Because of Classloaders
How to Store Original Date/Time Without Timezone Calculation to Mongodb
Converting Excel File (Xlsx) into Json
Android Room Persistent: Appdatabase_Impl Does Not Exist
Limiting the Number of Characters in a String, and Chopping Off the Rest
How to Get an Http Response Body as a String
How to Get File Extension from Content Type
Generate Any Random Number of Any Length in Java
Using an Empty Keystore Password Used to Be Possible
Where Does Gradle Save Dependencies' Jars
Subscript and Superscript a String in Android
How to Junit Test That Two List<E> Contain the Same Elements in the Same Order
How to Create a Java Code to Check Multiple Question
Hibernate Foreign Key Issue:Error Executing Ddl "Alter Table..."
When I Run Mockito Test Occurs Wrongtypeofreturnvalue Exception