需要使用ObjectMapper进行非静态内部类的MixIn解析-Java 6 [英] Need MixIn Resolution for non-static Inner Class using ObjectMapper - Java 6

查看:101
本文介绍了需要使用ObjectMapper进行非静态内部类的MixIn解析-Java 6的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将ObjectMapper用于非静态内部类时遇到了问题.我需要创建MixIn才能使其正常运行,但无法解决该问题.下面是我的课程(我无法更改)和MixIn,我尝试过.创建此类MixIn所需的帮助.

I'm facing an issue while using ObjectMapper for non-static inner class. I need to create MixIn to make it work but could not reach to the solution. Below is my class(which I can't change) and the MixIn, I tried. Help needed to create such MixIn.

===========================

============================

基类

    public class NestedClass implements Serializable{

    private static final long serialVersionUID = -4509619645418618657L;

    private NestedInnerClass innerClass;

    public NestedClass() {
        innerClass = null;
        setInnerClass(new NestedInnerClass(new NestedInnerClass2(), new NestedInnerClass3()));
    }

    public NestedClass(NestedClass nestedCls) {
        innerClass = null;
        setInnerClass(nestedCls.getInnerClass());
    }

    public class NestedInnerClass implements Serializable{
        private static final long serialVersionUID = 9099474732768960830L;
        NestedClass.NestedInnerClass2 nestedInnerClass2;
        NestedClass.NestedInnerClass3 nestedInnerClass3;

        public NestedInnerClass() { 
            super();
        }

        public NestedInnerClass(NestedInnerClass2 nestedInnerClass2, NestedInnerClass3 nestedInnerClass3) {
            super();
            this.nestedInnerClass2 = nestedInnerClass2;
            this.nestedInnerClass3 = nestedInnerClass3;
        }

        public NestedClass.NestedInnerClass2 getNestedInnerClass2() {
            return nestedInnerClass2;
        }

        public void setNestedInnerClass2(NestedClass.NestedInnerClass2 nestedInnerClass2) {
            this.nestedInnerClass2 = nestedInnerClass2;
        }

        public NestedClass.NestedInnerClass3 getNestedInnerClass3() {
            return nestedInnerClass3;
        }

        public void setNestedInnerClass3(NestedClass.NestedInnerClass3 nestedInnerClass3) {
            this.nestedInnerClass3 = nestedInnerClass3;
        }

    }

    public class NestedInnerClass2 implements Serializable{

        private static final long serialVersionUID = -3451502802923307744L;
        String nestedString;
        HashMap<String, String> nestedHashMap = new HashMap<String, String>();

        public NestedInnerClass2() {
            super();
        }

        public NestedInnerClass2(String nestedString, HashMap<String, String> nestedHashMap) {
            super();
            this.nestedString = nestedString;
            this.nestedHashMap = nestedHashMap;
        }

        public NestedInnerClass2(String nestedString) {
            this.nestedString = nestedString;
        }

        public String getNestedString() {
            return nestedString;
        }

        public void setNestedString(String nestedString) {
            this.nestedString = nestedString;
        }

        public HashMap<String, String> getNestedHashMap() {
            return nestedHashMap;
        }

        public void setNestedHashMap(HashMap<String, String> nestedHashMap) {
            this.nestedHashMap = nestedHashMap;
        }

    }

    public class NestedInnerClass3 implements Serializable{

        private static final long serialVersionUID = 1799737022784300052L;
        String nestedString;

        public NestedInnerClass3() {
            super();
        }

        public NestedInnerClass3(String nestedString) {
            super();
            this.nestedString = nestedString;
        }

        public String getNestedString() {
            return nestedString;
        }

        public void setNestedString(String nestedString) {
            this.nestedString = nestedString;
        }

    }

    public NestedInnerClass getInnerClass() {
        return innerClass;
    }

    public void setInnerClass(NestedInnerClass innerClass) {
        this.innerClass = innerClass;
    }


}

================================

=================================

嵌套类的子类:

public class NestedClassChild extends NestedClass implements Serializable, Cloneable{

    private static final long serialVersionUID = 7022339501842754692L;

    public NestedClassChild() {}
}

================================

=================================

协助班级:

public class NestedClassAssist {

    public static void setNestedValues(NestedClass nestedClass, String key, String value, String nestedString)
    {
        if(nestedClass != null && nestedClass.getInnerClass() != null && nestedClass.getInnerClass().getNestedInnerClass2() != null)
        {
            HashMap<String, String> hashMap = new HashMap<String, String>();
            hashMap.put(key, value);
            nestedClass.getInnerClass().getNestedInnerClass2().setNestedHashMap(hashMap);
            nestedClass.getInnerClass().getNestedInnerClass2().setNestedString(nestedString);
        }
    }

     public static void setValue(NestedClass nestedClass, String value){
         setNestedValues(nestedClass, "keyStr", value, "ABC");
     }
}

================================

=================================

要转换为JSON有效负载:

To convert to JSON payload :

public class NestedClassToJson {

    public static void main(String[] args) {
        NestedClassChild nestedClassChild = new NestedClassChild();
        NestedClassAssist.setValue(nestedClassChild, "12345");

        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.writerWithDefaultPrettyPrinter();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);

        try {
            mapper.writeValue(new File("json/testNested.json"),nestedClassChild);
        } catch (Exception e) {  
            e.printStackTrace();
        }
    }
}

================================

=================================

从上述类生成的JSON有效负载:

Generated JSON payload from above class :

{
  "innerClass" : {
    "nestedInnerClass2" : {
      "nestedString" : "ABC",
      "nestedHashMap" : {
        "keyStr" : "12345"
      }
    },
    "nestedInnerClass3" : {
      "nestedString" : null
    }
  }
}

================================

=================================

要从JSON反序列化的类:

Class to de-serialize from JSON :

public class NestedClassFromJson {

    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.writerWithDefaultPrettyPrinter();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);

        NestedClass objectNested = mapper.readValue(getPostBodyAsJSON(), NestedClassChild.class);
        System.out.println(mapper.writeValueAsString(objectNested));
    }

    private static String getPostBodyAsJSON() {
        StringBuffer postBody = new StringBuffer();
        String line = null;
        try {
            BufferedReader reader = new BufferedReader(new FileReader(new File("json/testNested.json")));
            while ((line = reader.readLine()) != null)
                postBody.append(line);
        } catch (IOException e) {
            throw new RuntimeException("Issue Occured While Reading POST Body", e);
        }

        return postBody.toString();
    }
}

================================

=================================

但是我低于Exception(尽管我确实具有默认构造函数):

But I'm getting below Exception (though I do have default contructor) :

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.test.jackson.NestedClass$NestedInnerClass]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
 at [Source: {  "innerClass" : {    "nestedInnerClass2" : {      "nestedString" : "ABC",      "nestedHashMap" : {        "keyStr" : "12345"      }    },    "nestedInnerClass3" : {      "nestedString" : null    }  }}; line: 1, column: 24] (through reference chain: com.test.jackson.NestedClassChild["innerClass"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1106)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:296)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
    at com.test.jackson.NestedClassFromJson.main(NestedClassFromJson.java:21)

================================

=================================

我尝试但没有用的嵌套MixIn:

Nested MixIn which I tried but didn't work:

public abstract class NestedMixIn {

    @JsonCreator
    public NestedMixIn(@JsonProperty("innerClass") NestedInnerClass innerClass ) {
    }

    public static class SourceIdInnerMixin{

        @JsonCreator
        public SourceIdInnerMixin(@JsonProperty("nestedInnerClass2") NestedInnerClass2 nestedInnerClass2, 
                @JsonProperty("nestedInnerClass3") NestedInnerClass3 nestedInnerClass3) {
        }
    }
}

=========================

==========================

如果我将内部类设为static,则可以使用,但是由于它是3rd party类,因此无法更改.

If I make the inner classes static , it works but since it is 3rd party class, I can't change it.

将感谢您的帮助!

推荐答案

在您的示例中,我没有注意到父类和嵌套类之间的任何关系.您还提到过可以将其更改为静态并且可以工作,因此我们要做的就是为反序列化过程提供内部类的实例.默认情况下,Jackson使用com.fasterxml.jackson.databind.deser.BeanDeserializerJSON Object映射到给定的类.我们可以扩展它并注册供应商以实例化对象.

In your example, I did not notice any relation between parent class and nested classes. Also you mentioned you can change it to static and it works, so all we need to do, is provide an instance of inner class to deserialisation process. By default Jackson uses com.fasterxml.jackson.databind.deser.BeanDeserializer to map JSON Object to a given class. We can extend it and register suppliers to instantiate objects.

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.function.Supplier;

public class JsonNestedApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        SimpleModule nestedModule = new SimpleModule();
        nestedModule.setDeserializerModifier(new NestedBeanDeserializerModifier());

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(nestedModule);
        // other configuration

        NestedClass nestedClass = mapper.readValue(jsonFile, NestedClass.class);
        System.out.println(nestedClass);
    }
}

class NestedBeanDeserializerModifier extends BeanDeserializerModifier {

    private final NestedClass parent = new NestedClass();
    private final Map<Class, Supplier> availableSuppliers = new HashMap<>();

    public NestedBeanDeserializerModifier() {
        availableSuppliers.put(NestedClass.NestedInnerClass2.class, () -> parent.new NestedInnerClass2());
        availableSuppliers.put(NestedClass.NestedInnerClass3.class, () -> parent.new NestedInnerClass3());
    }

    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        final Supplier supplier = availableSuppliers.get(beanDesc.getBeanClass());
        if (supplier != null) {
            return new NestedBeanDeserializer((BeanDeserializerBase) deserializer, supplier);
        }

        return deserializer;
    }
}

class NestedBeanDeserializer extends BeanDeserializer {

    private final Supplier supplier;

    protected NestedBeanDeserializer(BeanDeserializerBase src, Supplier supplier) {
        super(src);
        this.supplier = Objects.requireNonNull(supplier);
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        return super.deserialize(p, ctxt, supplier.get());
    }
}

以上代码应成功反序列化JSON有效负载.

Above code should deserialise JSON payload with success.

这篇关于需要使用ObjectMapper进行非静态内部类的MixIn解析-Java 6的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆