Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Jackson to validate duplicated properties?

Tags:

java

json

jackson

I'm using Jackson JSON library to convert some JSON objects to POJO classes. The problem is, when I use JSON Objects with duplicated properties like:

{
  "name":"xiaopang",
  "email":"[email protected]",
  "email":"[email protected]"
}

Jackson report the last email pair "email":"[email protected]" and then parse the object.

I've learned from Does JSON syntax allow duplicate keys in an object? that what happens when deserializing a JSON object with duplicate properties depends on the library implementation, either throwing an error or using the last one for duplicate key.

Despite overheads of tracking all properties, is there any way to tell Jackson to report an error or exception such as "Duplicate key" in this case?

like image 288
taoxiaopang Avatar asked May 11 '16 03:05

taoxiaopang


Video Answer


1 Answers

Use JsonParser.Feature.STRICT_DUPLICATE_DETECTION

ObjectMapper mapper = new ObjectMapper();
mapper.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
MyPOJO result = mapper.readValue(json, MyPOJO.class);

Results in:

Exception in thread "main" com.fasterxml.jackson.core.JsonParseException: Duplicate field 'email'

You can also try to use DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY (more info) It will be trigggered if you deserialize your json string/input to jackson json tree first and then to you POJO. Can combine it with custom JsonDeserializer like this:

private static class MyPojoDeserializer extends JsonDeserializer<MyPOJO>{

    @Override
    public MyPOJO deserialize(JsonParser p, DeserializationContext ctxt) 
                                                           throws IOException{
        JsonNode tree = p.readValueAsTree();
        return  p.getCodec().treeToValue(tree, MyPOJO.class);
    }
}

Setup it once and use it same way as before:

// setup ObjectMapper 
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
SimpleModule module = new SimpleModule();
module.addDeserializer(MyPOJO.class,new MyPojoDeserializer() );
mapper.registerModule(module);

// use
mapper.readValue(json, MyPOJO.class);

Result:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Duplicate field 'email' for ObjectNode: not allowed when FAIL_ON_READING_DUP_TREE_KEY enabled

Other options would be to implement all the logic yourself in custom deserializer or in you POJO setter methods.

like image 106
varren Avatar answered Oct 06 '22 01:10

varren