I have a class (which cannot be modified) like
public class Standing {
private Integer positionNumber;
private String positionText;
private BigDecimal points;
..
}
When deserializing I get data like:
{
"position": "1",
"points": 10
}
As I cannot modify the Standing
class I have a mix-in like:
@JsonDeserialize(converter = StandingSanitizer.class)
public abstract class StandingMixIn {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
Integer positionNumber;
@JsonProperty(value = "position", access = JsonProperty.Access.WRITE_ONLY)
String positionText;
}
As the received json does not have positionNumber
and positionText
fields I use the @JsonPropery
annotations.
With Access.READ_ONLY
I simply ignore the positionNumber
field.
And with @JsonProperty(value = "position", access = JsonProperty.Access.WRITE_ONLY)
on the positionText
field I make sure it's populated with the position
field from the json during deserialization.
This works well during deserialization.
Note the StandingSanitizer
sets the positionNumber
. This as the received position
value can be non-number values like DSQ
in which case the positionNumber
field will be null
.
But when serializing I want to output all 3 fields from the Standing
class like:
{
"positionText": "1",
"positionNumber": 1,
"points": 10
}
But because of @JsonProperty(value = "position", access = JsonProperty.Access.WRITE_ONLY)
on the positionText
field it is not serialized unfortunately.
In theory I would like to do have something like:
@JsonDeserialize(converter = StandingSanitizer.class)
public abstract class StandingMixIn {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
Integer positionNumber;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
@JsonProperty(value = "position", access = JsonProperty.Access.WRITE_ONLY)
String positionText;
}
where I could use different @JsonProperty
annotation for both READ and WRITE.
But this is not possible as duplicate @JsonProperty
annotations on a field are not allowed; and as far as I could see there is no support for repeatable annotations.
Is there any other solution to solve this?
One thing I can think of is to have 2 ObjectMapper
instances, with 2 different StandingMixIns
; 1 for deserializing and 1 for serializing. But I would prefer to keep having 1 ObjectMapper
instance, so using 2 would be a last resort.
CodePudding user response:
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;
}
}
CodePudding user response:
Thanks @Franjavi, you are indeed right I should use annotations on the getters/setters and not on the field only. I was to focussed on only using the fields as my mix-in classes are written in Groovy with implicit getters/setters.
I slimmed down the class a bit more to just:
public abstract class StandingMixIn {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
Integer positionNumber;
@JsonProperty(value = "positionText")
public abstract String getPositionText();
@JsonProperty(value = "position")
public abstract void setPositionText(String positionText);
}
(removing the positionText
completely and using abstract methods)