Java 如何将注入与XmlMapper反序列化一起使用

Java 如何将注入与XmlMapper反序列化一起使用,java,xml,jackson,spring-config,jackson-dataformat-xml,Java,Xml,Jackson,Spring Config,Jackson Dataformat Xml,我正在使用com.fasterxml.jackson.dataformat.xml中的XmlMapper。 我正在序列化的类有一个未序列化的Autowired成员 我希望能够将XML反序列化为一个实例,并使用Spring填充自动连接的成员变量 有没有办法做到这一点?ObjectMapper有一个方法,允许注册一些我们想在序列化过程中使用的外部bean。例如,DeserializationContext类有一个方法,该方法允许按名称查找上下文中以前注册的bean。下面你们可以找到一个例子,它展示了

我正在使用
com.fasterxml.jackson.dataformat.xml
中的
XmlMapper
。 我正在序列化的类有一个未序列化的
Autowired
成员

我希望能够将
XML
反序列化为一个实例,并使用
Spring
填充自动连接的成员变量


有没有办法做到这一点?

ObjectMapper
有一个方法,允许注册一些我们想在
序列化过程中使用的外部bean。例如,
DeserializationContext
类有一个方法,该方法允许按名称查找上下文中以前注册的bean。下面你们可以找到一个例子,它展示了如何做到这一点的一般思路。首先,声明一个要自动连线的可注入bean:

class InjectBean {

    private int key = ThreadLocalRandom.current().nextInt();

    @Override
    public String toString() {
        return "key => " + key;
    }
}
我们希望从
XML
反序列化的
POJO
类可以如下所示:

class Pojo {

    private String name;
    private InjectBean dependency;

    // getters, setters, toString
}
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.InjectableValues;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
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 com.fasterxml.jackson.dataformat.xml.XmlMapper;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;

public class XmlMapperApp {

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

        InjectBean injectBean = autowire();
        InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue(PojoBeanDeserializer.DEPENDENCY_NAME, injectBean);

        SimpleModule injectModule = new SimpleModule();
        injectModule.setDeserializerModifier(new InjectBeanDeserializerModifier());

        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.registerModule(injectModule);
        xmlMapper.setInjectableValues(injectableValues);

        Pojo bean = xmlMapper.readValue(xmlFile, Pojo.class);

        System.out.println("After deserialization:");
        System.out.println(bean);
    }

    private static InjectBean autowire() {
        InjectBean bean = new InjectBean();

        System.out.println("Injectable bean from context: " + bean);

        return bean;
    }
}

class InjectBeanDeserializerModifier extends BeanDeserializerModifier {
    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        if (beanDesc.getType().getRawClass() == Pojo.class) {
            JsonDeserializer<?> jsonDeserializer = super.modifyDeserializer(config, beanDesc, deserializer);

            return new PojoBeanDeserializer((BeanDeserializer) jsonDeserializer);
        }

        return super.modifyDeserializer(config, beanDesc, deserializer);
    }
}
现在,我们需要实现自定义反序列化程序,该程序将注入自动连线字段:

class PojoBeanDeserializer extends BeanDeserializer {

    public static final String DEPENDENCY_NAME = "injectBean";

    public PojoBeanDeserializer(BeanDeserializerBase src) {
        super(src);
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Object deserialize = super.deserialize(p, ctxt);
        InjectBean injectableValue = findInjectableValue(ctxt);

        Pojo pojo = (Pojo) deserialize;
        pojo.setDependency(injectableValue);

        return deserialize;
    }

    private InjectBean findInjectableValue(DeserializationContext context) throws JsonMappingException {
        return (InjectBean) context.findInjectableValue(DEPENDENCY_NAME, null, null);
    }
}
上述反序列化程序只能用于
Pojo
类。如果您需要对许多类执行相同的操作,您可以将
setDependency
方法提取到一个接口,并通过每个
POJO
以相同的方式实现该接口。在上面的反序列化程序中,您可以转换到接口,而不是转换到
Pojo
。要注册我们的自定义反序列化程序,我将使用
BeanDeserializerModifier
,但您可以用其他方式进行注册。例如,如果您已经有了自定义反序列化程序,并且使用了
@JsonDeserialize
注释,则不需要这样做。简单用法如下所示:

class Pojo {

    private String name;
    private InjectBean dependency;

    // getters, setters, toString
}
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.InjectableValues;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
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 com.fasterxml.jackson.dataformat.xml.XmlMapper;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;

public class XmlMapperApp {

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

        InjectBean injectBean = autowire();
        InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue(PojoBeanDeserializer.DEPENDENCY_NAME, injectBean);

        SimpleModule injectModule = new SimpleModule();
        injectModule.setDeserializerModifier(new InjectBeanDeserializerModifier());

        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.registerModule(injectModule);
        xmlMapper.setInjectableValues(injectableValues);

        Pojo bean = xmlMapper.readValue(xmlFile, Pojo.class);

        System.out.println("After deserialization:");
        System.out.println(bean);
    }

    private static InjectBean autowire() {
        InjectBean bean = new InjectBean();

        System.out.println("Injectable bean from context: " + bean);

        return bean;
    }
}

class InjectBeanDeserializerModifier extends BeanDeserializerModifier {
    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        if (beanDesc.getType().getRawClass() == Pojo.class) {
            JsonDeserializer<?> jsonDeserializer = super.modifyDeserializer(config, beanDesc, deserializer);

            return new PojoBeanDeserializer((BeanDeserializer) jsonDeserializer);
        }

        return super.modifyDeserializer(config, beanDesc, deserializer);
    }
}
印刷品:

Injectable bean from context: key => 909636975
After deserialization:
Bean{name='Tom', dependency=key => 909636975}
另见:


ObjectMapper
有一种方法,允许注册一些我们希望在
序列化过程中使用的外部bean。例如,
DeserializationContext
类有一个方法,该方法允许按名称查找上下文中以前注册的bean。下面你们可以找到一个例子,它展示了如何做到这一点的一般思路。首先,声明一个要自动连线的可注入bean:

class InjectBean {

    private int key = ThreadLocalRandom.current().nextInt();

    @Override
    public String toString() {
        return "key => " + key;
    }
}
我们希望从
XML
反序列化的
POJO
类可以如下所示:

class Pojo {

    private String name;
    private InjectBean dependency;

    // getters, setters, toString
}
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.InjectableValues;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
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 com.fasterxml.jackson.dataformat.xml.XmlMapper;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;

public class XmlMapperApp {

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

        InjectBean injectBean = autowire();
        InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue(PojoBeanDeserializer.DEPENDENCY_NAME, injectBean);

        SimpleModule injectModule = new SimpleModule();
        injectModule.setDeserializerModifier(new InjectBeanDeserializerModifier());

        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.registerModule(injectModule);
        xmlMapper.setInjectableValues(injectableValues);

        Pojo bean = xmlMapper.readValue(xmlFile, Pojo.class);

        System.out.println("After deserialization:");
        System.out.println(bean);
    }

    private static InjectBean autowire() {
        InjectBean bean = new InjectBean();

        System.out.println("Injectable bean from context: " + bean);

        return bean;
    }
}

class InjectBeanDeserializerModifier extends BeanDeserializerModifier {
    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        if (beanDesc.getType().getRawClass() == Pojo.class) {
            JsonDeserializer<?> jsonDeserializer = super.modifyDeserializer(config, beanDesc, deserializer);

            return new PojoBeanDeserializer((BeanDeserializer) jsonDeserializer);
        }

        return super.modifyDeserializer(config, beanDesc, deserializer);
    }
}
现在,我们需要实现自定义反序列化程序,该程序将注入自动连线字段:

class PojoBeanDeserializer extends BeanDeserializer {

    public static final String DEPENDENCY_NAME = "injectBean";

    public PojoBeanDeserializer(BeanDeserializerBase src) {
        super(src);
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Object deserialize = super.deserialize(p, ctxt);
        InjectBean injectableValue = findInjectableValue(ctxt);

        Pojo pojo = (Pojo) deserialize;
        pojo.setDependency(injectableValue);

        return deserialize;
    }

    private InjectBean findInjectableValue(DeserializationContext context) throws JsonMappingException {
        return (InjectBean) context.findInjectableValue(DEPENDENCY_NAME, null, null);
    }
}
上述反序列化程序只能用于
Pojo
类。如果您需要对许多类执行相同的操作,您可以将
setDependency
方法提取到一个接口,并通过每个
POJO
以相同的方式实现该接口。在上面的反序列化程序中,您可以转换到接口,而不是转换到
Pojo
。要注册我们的自定义反序列化程序,我将使用
BeanDeserializerModifier
,但您可以用其他方式进行注册。例如,如果您已经有了自定义反序列化程序,并且使用了
@JsonDeserialize
注释,则不需要这样做。简单用法如下所示:

class Pojo {

    private String name;
    private InjectBean dependency;

    // getters, setters, toString
}
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.InjectableValues;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
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 com.fasterxml.jackson.dataformat.xml.XmlMapper;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;

public class XmlMapperApp {

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

        InjectBean injectBean = autowire();
        InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue(PojoBeanDeserializer.DEPENDENCY_NAME, injectBean);

        SimpleModule injectModule = new SimpleModule();
        injectModule.setDeserializerModifier(new InjectBeanDeserializerModifier());

        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.registerModule(injectModule);
        xmlMapper.setInjectableValues(injectableValues);

        Pojo bean = xmlMapper.readValue(xmlFile, Pojo.class);

        System.out.println("After deserialization:");
        System.out.println(bean);
    }

    private static InjectBean autowire() {
        InjectBean bean = new InjectBean();

        System.out.println("Injectable bean from context: " + bean);

        return bean;
    }
}

class InjectBeanDeserializerModifier extends BeanDeserializerModifier {
    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        if (beanDesc.getType().getRawClass() == Pojo.class) {
            JsonDeserializer<?> jsonDeserializer = super.modifyDeserializer(config, beanDesc, deserializer);

            return new PojoBeanDeserializer((BeanDeserializer) jsonDeserializer);
        }

        return super.modifyDeserializer(config, beanDesc, deserializer);
    }
}
印刷品:

Injectable bean from context: key => 909636975
After deserialization:
Bean{name='Tom', dependency=key => 909636975}
另见:


你看到我的答案了吗?这对你有帮助吗?你看到我的答案了吗?这对你有帮助吗?