Home > Blockchain >  Different @JsonProperty config for READ and WRITE on same field?
Different @JsonProperty config for READ and WRITE on same field?

Time:10-02

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)

  • Related