简体   繁体   中英

Jackson: ignore unknown enum values

I'm trying to deserialize a JSON object obtained from a RESTful webservice. I have the following class:

public class ACE {
    private Persona trustee;
    private String accesstype;
    private final Set<Right> accessrights = EnumSet.noneOf(Right.class);
    private final Set<Inheritance> inherit_flags
            = EnumSet.noneOf(Inheritance.class);
    private String op;

    public static enum Right {
        traverse, list, dir_read_attr, dir_read_ext_attr, add_file, add_subdir,
        dir_write_attr, dir_write_ext_attr, delete_child, std_delete,
        std_read_dac, std_write_dac, std_write_owner,

        dir_gen_all, dir_gen_execute, dir_gen_read, dir_gen_write, modify;
    }

    public static enum Inheritance {
        object_inherit, container_inherit, no_prop_inherit, inherit_only,
        inherited_ace;
    }

    public ACE setAccessrights(Set<Right> rights) {
        accessrights.clear();
        accessrights.addAll(rights);
        return this;
    }
...

Now the webservices returns 'std_synchronize' in the set 'accessrights', which is a value that is not defined in the Right enum type.

I'm getting the following exception:

    com.fasterxml.jackson.databind.JsonMappingException: N/A (through reference chain: gina.nas.ws.ACL["acl"]->gina.nas.ws.ACE["accessrights"])
            at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:421)
            at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:404)
            at com.fasterxml.jackson.databind.deser.impl.MethodProperty.set(MethodProperty.java:116)
            at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)
            at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308)
            at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
            at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:147)
            at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:18)
            at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375)
            at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)
            at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308)
            at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
            at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2793)
            at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1989)
            at gina.nas.ws.NasSession.getACL(NasSession.java:188)
            at gina.nas.NasAPI.getSecurity(NasAPI.java:451)
            at gina.nas.NasAPI.getSecurity(NasAPI.java:244)
        at gina.nas.NasHelper.setStructureUOACL(NasHelper.java:622)
        at gina.nas.NasHelper.setStructureUOACL(NasHelper.java:263)
        at gina.nas.NasHelper.setStructureUOACL(NasHelper.java:280)
        at gina.nas.NasHelper.setStructureUOACL(NasHelper.java:299)
        at gina.nas.NasHelper.setStructureUOACL(NasHelper.java:317)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:126)
        ... 13 more
Caused by: java.lang.NullPointerException
        at java.util.EnumSet.typeCheck(Unknown Source)
        at java.util.RegularEnumSet.add(Unknown Source)
        at java.util.RegularEnumSet.add(Unknown Source)
        at java.util.AbstractCollection.addAll(Unknown Source)
        at java.util.RegularEnumSet.addAll(Unknown Source)
        at gina.nas.ws.ACE.setAccessrights(ACE.java:51)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:97)
        ... 38 more

I have set the following flag in the ObjectMapper:

mapper.configure(
        DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);

but the problem seems to arise when jackson tries to add null to the set.

Is there a way to simply ignore unknown values?

Another way would be to fallback to a default enum value for unknowns. You can do that by annotating a enum field that should be default with @JsonEnumDefaultValue and enabling DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE on your ObjectMapper.

Refer below for example:

Changes on enum

public static enum Right { 
      traverse, list, dir_read_attr, dir_read_ext_attr, add_file, 
      add_subdir, dir_write_attr, dir_write_ext_attr, delete_child, std_delete, 
      std_read_dac, std_write_dac, std_write_owner, dir_gen_all, dir_gen_execute, 
      dir_gen_read, dir_gen_write, modify,
      @JsonEnumDefaultValue UNKNOWN; 
}

Changes on ObjectMapper

ObjectMapper().enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);

I did not manage to reproduce your problem with jackson 2.5.1

This is my ACE class

public class ACE {
    private final Set<Right> accessrights = EnumSet.noneOf(Right.class);
    private final Set<Inheritance> inherit_flags
            = EnumSet.noneOf(Inheritance.class);

    public static enum Right {
        traverse, list, dir_read_attr, dir_read_ext_attr, add_file, add_subdir,
        dir_write_attr, dir_write_ext_attr, delete_child, std_delete,
        std_read_dac, std_write_dac, std_write_owner,
        dir_gen_all, dir_gen_execute, dir_gen_read, dir_gen_write, modify;
    }

    public static enum Inheritance {
        object_inherit, container_inherit, no_prop_inherit, inherit_only,
        inherited_ace;
    }

    public Set<Right> getAccessrights() {
        return accessrights;
    }

    public Set<Inheritance> getInherit_flags() {
        return inherit_flags;
    }

}

this is my test case:

package test;

import test.ACE.Inheritance;
import test.ACE.Right;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestJacksonEnum {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        ACE ace= new ACE();
        ace.getAccessrights().add(Right.add_file);
        ace.getAccessrights().add(Right.add_subdir);
        ace.getInherit_flags().add(Inheritance.container_inherit);
        ace.getInherit_flags().add(Inheritance.inherit_only);
        ObjectMapper mapper=new ObjectMapper();
        mapper.configure(
                DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
        System.out.println(mapper.writeValueAsString(ace));
        String serializedFormREST="{\"accessrights\":[\"std_synchronize\",\"add_subdir\"],\"inherit_flags\":[\"container_inherit\",\"inherit_only\"]}";
        ACE deserializedAce= mapper.readValue(serializedFormREST, ACE.class);
        System.out.println(mapper.writeValueAsString(deserializedAce));
    }


}

The deserializedAce object is read correctly and the set does not contain std_synchronize but it contains a null. Am I missing something?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM