30

I'm using Jackson's readValue() method on an object mapper to read from a JSON file and convert it into my java object.

eg.

mapperObject.readValue( node, MyTargetClass.class )

Are there any annotations that I can set on MyTargetClass to enforce required attributes? For example, if I have a JSON object with properties ABC,DEF and GHI, and my Json is the following

{
  "ABC" : "somevalue"
  "DEF" : "someothervalue" 
}

I want it to fail somehow, and only succeed on the readValue if it contained ABC, DEF and GHI.

Ren
  • 3,395
  • 2
  • 27
  • 46

4 Answers4

25

You can mark a property as required with the @JsonProperty(required = true) annotation, and it will throw a JsonMappingException during deserialization if the property is missing or null.

Edit: I received a downvote for this without comment. I'd love to know why, since it does exactly the right thing.

postfuturist
  • 22,211
  • 11
  • 65
  • 85
  • Hello. Maybe because it doesn't work yet. See: http://stackoverflow.com/questions/18320731/jackson-jsonpropertyrequired-true-doesnt-throw-an-exception – Gunith D Nov 10 '16 at 05:09
  • 1
    @GunithDevasurendra It does work in recent versions of Jackson. – postfuturist Nov 10 '16 at 20:25
  • 2
    I'm using 2.7.3 and it works. However, I found one case where it doesn't: annotating builder methods when using @JsonDeserialize(builder = Foo.Builder.class). – postfuturist Nov 11 '16 at 18:48
  • i am using spring boot 1.5.9.RELEASE which uses jackson-core 2.8.10 and jackson-annotations 2.8.0 and it doesn't seem to work – abdel Feb 07 '18 at 16:52
  • i checked the source code on 2.8.0 and its javadoc says " Note that as of 2.6, this property is only used for Creator Properties, to ensure existence of property value in JSON: for other properties (ones injected using a setter or mutable field), no validation is performed. Support for those cases may be added in future. State of this property is exposed via introspection, and its value is typically used by Schema generators, such as one for JSON Schema." – abdel Feb 07 '18 at 17:03
  • It works only if you use @JsonProperty in your POJO constructor parameters ! Please note that you have also to set the JsonProperty#value attribute even if this the same as your property's name – Eric Taix Feb 22 '18 at 15:48
  • 3
    this is just not correct. `@JsonProperty(required = true)` ONLY works for serialization, NOT deserialization – Javier Aviles Jun 19 '19 at 13:31
24

Jackson does not include validation functionality, and this is by design (i.e. that is considered out-of-scope). But what is usually used is Bean Validation API implementation. The nice thing about this is decoupling between data format handling, and validation logic. This is what frameworks like DropWizard use; and it's the direction JAX-RS (like Jersey) are taking things for JAX-RS 2.0.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • Any examples of how do you use `Bean Validation API` with `readValue()` please? – Klesun Apr 09 '20 at 18:57
  • The very first hit googling "jackson validation with bean validation"? https://www.baeldung.com/javax-validation -- not within `readValue()`, first you read (bind), then validate. – StaxMan Apr 10 '20 at 20:42
  • 2
    Thanks, I also eventually ended on that link after few hours of searching. My first google hit was this answer. – Klesun Apr 12 '20 at 03:01
6

If you want to make sure a json field is provided, you have to use the @JsonProperty(value = "fieldName", required = true) annotation as a parameter to the constructor. But this is not enough, also the Constructor should have @JsonCreator annotation.

For example, if you have a field named 'endPoint' and you want o make sure it is provided in the JSON file, then the following code will throw an exception if it is not provided.

@JsonCreator
public QuerySettings(@JsonProperty(value = "endPoint", required = true) String endPoint) {
        this.endPoint = endPoint;
}

I found this link helpful to understand the Jackson annotations. It also well explains why required=true is not enough and counter-intuitive to its name.

Memin
  • 3,788
  • 30
  • 31
1

If you are neither satisfied with using @JsonProperty(required = true) as it works only with @JsonCreator nor with the use of bean validation then one more way of tackling it would be to catch this in your setter methods for the relevant variables.

You can simply check if the variable is null before setting it and throw an IllegalArgumentException or NullPointerException (as preferred by few people)

Note: It depends on how your POJO is defined too, so please make sure that it is going the setter method route for this solution to work.

Vikas Tawniya
  • 1,323
  • 1
  • 13
  • 22