java Jackson 反序列化抽象类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44374706/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 08:08:51  来源:igfitidea点击:

Hymanson Deserialize Abstract Classes

javaspringspring-bootHymanson

提问by Punter Vicky

I am trying to deserialize an object using JSON ObjectMapper. I see the below error when trying to deserialize

我正在尝试使用 JSON ObjectMapper 反序列化一个对象。尝试反序列化时,我看到以下错误

com.fasterxml.Hymanson.databind.JsonMappingException: Can not construct instance of com.phoenix.types.OrderItem: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information at [Source: java.io.StringReader@4bb33f74; line: 112, column: 7] (through reference chain: com.phoenix.types.GenerateRequest["order"]->com.phoenix.types.Order["orderItems"]->Object[][0]) at com.fasterxml.Hymanson.databind.JsonMappingException.from(JsonMappingException.java:261) at com.fasterxml.Hymanson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456) at com.fasterxml.Hymanson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1012) at com.fasterxml.Hymanson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:149) at com.fasterxml.Hymanson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:196) at com.fasterxml.Hymanson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:20) at com.fasterxml.Hymanson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499) at com.fasterxml.Hymanson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:101) at com.fasterxml.Hymanson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276) at com.fasterxml.Hymanson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140) at com.fasterxml.Hymanson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499) at com.fasterxml.Hymanson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:101) at com.fasterxml.Hymanson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276) at com.fasterxml.Hymanson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140) at com.fasterxml.Hymanson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789) at com.fasterxml.Hymanson.databind.ObjectMapper.readValue(ObjectMapper.java:2833)

com.fasterxml.Hymanson.databind.JsonMappingException:无法构造 com.phoenix.types.OrderItem 的实例:抽象类型需要映射到具体类型、具有自定义反序列化器或在 [来源:java.io .StringReader@4bb33f74; 行:112,列:7](通过参考链:com.phoenix.types.GenerateRequest["order"]->com.phoenix.types.Order["orderItems"]->Object[][0])在com .fasterxml.Hymanson.databind.JsonMappingException.from(JsonMappingException.java:261) at com.fasterxml.Hymanson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456) at com.fasterxml.Hymanson.databind.DeserializationContext.handleMissingeri .java:1012) 在 com.fasterxml.Hymanson.databind.deser。

I came across this postfor performing polymorphic deserialization. This basically provides the solution for resolving the error listed above. The classes (In this instance OrderItem etc) that I am using for deserialization are part of a jar file. However is there a way to define JsonDeserialize as part of objectmapper when trying to deserialize instead of adding annotation to the class itself as I don't have access to it.

我碰到这个来进行多态性反序列化。这基本上提供了解决上面列出的错误的解决方案。我用于反序列化的类(在此实例中为 OrderItem 等)是 jar 文件的一部分。但是,在尝试反序列化而不是向类本身添加注释时,有没有一种方法可以将 JsonDeserialize 定义为 objectmapper 的一部分,因为我无权访问它。

回答by Andrew Rueckert

Yes, you can write your own Custom Deserializerfor the abstract class. This deserializer will have to determine which concrete class the JSON represents, and instantiate an instance of it.

是的,您可以为抽象类编写自己的自定义反序列化器。这个反序列化器必须确定 JSON 代表哪个具体类,并实例化它的一个实例。

There is likely a more idiomatic way of doing this, but here is a quick-and-dirty example:

可能有一种更惯用的方法来做到这一点,但这里有一个快速而肮脏的例子:

public class Test {
    public static void main(String... args) throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        final SimpleModule module = new SimpleModule();
        module.addDeserializer(Animal.class, new AnimalDeserializer());
        mapper.registerModule(module);

        final String json = "{\"aGoodBoy\": true}";
        final Animal animal = mapper.readValue(json, Animal.class);
        System.out.println(animal.talk());
    }

    public static abstract class Animal {
        public abstract String talk();
    }

    public static class Fish extends Animal {
        @Override
        public String talk() {
            return "blub blub I'm a dumb fish";
        }
    }

    public static class Dog extends Animal {
        public boolean aGoodBoy;

        @Override
        public String talk() {
            return "I am a " + (aGoodBoy ? "good" : "bad") + " dog";
        }
    }

    public static class AnimalDeserializer extends StdDeserializer<Animal> {
        protected AnimalDeserializer() {
            this(null);
        }

        protected AnimalDeserializer(final Class<?> vc) {
            super(vc);
        }

        @Override
        public Animal deserialize(final JsonParser parser, final DeserializationContext context)
        throws IOException, JsonProcessingException {
            final JsonNode node = parser.getCodec().readTree(parser);
            final ObjectMapper mapper = (ObjectMapper)parser.getCodec();
            if (node.has("aGoodBoy")) {
                return mapper.treeToValue(node, Dog.class);
            } else {
                return mapper.treeToValue(node, Fish.class);
            }
        }
    }
}

回答by Abhinav Atul