3
votes

Is it possible to have the @JsonProperty required dynamically set or set at call?

The reason behind this... I'm generating json files which describes a schema and defines

  • What are the required fields for a new item
  • What are the required fields for an update to an item.

So, a creation requires only foo

and an update requires foo and bar

Can I make things so I can pass in something to say bar is now required?

or would I need to duplicate this code in order to have different settings for JsonProperty?

@JsonInclude(Include.NON_NULL)

public class Bean {

    @JsonProperty(value="foo", required=false)
    private FooProperty fooProperty;

    @JsonProperty(value="bar", required=false)
    private BarProperty barProperty;

    //
    public FooProperty getFooProperty() { return fooProperty; }

    public void setFooProperty(FooProperty argFooProperty) {
        this.fooProperty = argFooProperty
    }


    public BarProperty getBarProperty() { return barProperty; }

    public void setFooProperty(BarProperty argBarProperty) {
        this.barProperty = argBarProperty
    }
}
3
can you explain your case a bit elaborately ?Coder
Added more details.Elijah
is it for serialization/deserialization? have you looked at custom serializer? Is using @JsonAnyGetter and @JsonAnySetter a viable option for you?Coder
I'll look into the JsonAnyGetter and JsonAnySetter right now and see where that leads me. This is all new to me. ThanksElijah
Yes the code is for serialization/deserialization.Elijah

3 Answers

3
votes

You could solve this issue in couple of ways. First one would be as Franjavi suggested you could use a mixin.

Have a mixin class which will mark your foo as one of the ignored properties. In your main class mark both the fiends required and you can inject this mixin whenever this is an option field.

@JsonIgnoreProperties("foo")
public abstract class mixinClass {

}

You configure your mixin into your mapper as follows.

ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Bean.class, mixinClass.class);

This is not always a working option whenever you are getting this response from a third party API where you might be serializing/deserializing using the default jackson mapper which are provided by them like Resttemplate.

In this case, instead of having the foo property, you can just included whatever the properties that are present in all the responses and handle the rest of the properties using @JsonAnyGetter and @JsonAnySetter. You can capture this in a map with key being your object name which is in this case foo. You need to have the following part in your parent node or whichever node that will encapsulates these optional properties.

@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}

@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}

Let me know if you need any further clarification!!

1
votes

You can play wiht Mixins and the mapper:

public interface BarRequiredMixIn {
    @JsonProperty(value="bar", required=true)
    private BarProperty barProperty;
}

ObjectMapper mapper = new ObjectMapper();
// When you want that it is required
mapper.addMixInAnnotations(Bean.class, BarRequiredMixIn.class);

But I strongly recommend to avoid to use this kind of conditional restrictions with Jackson, since it is not designed for it, and it looks kind of confusing.

0
votes

Based on the example you have given, setting the following in your POJO would be sufficient & Jackson would be able to figure out whether to deserialize it/not . All @JsonProperty are required by default, so with the code below, you would be able to achieve optional bar value in your Create/Update scenarios based on payload in the request

@JsonProperty(value="bar", required=false)
private Bar bar;