Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从Jackson中的自定义反序列化程序调用默认反序列化程序_Java_Spring_Hibernate_Jackson - Fatal编程技术网

Java 如何从Jackson中的自定义反序列化程序调用默认反序列化程序

Java 如何从Jackson中的自定义反序列化程序调用默认反序列化程序,java,spring,hibernate,jackson,Java,Spring,Hibernate,Jackson,我在Jackson的自定义反序列化程序中遇到问题。我想访问默认序列化程序来填充我要反序列化的对象。在填充之后,我将执行一些自定义操作,但首先我想用默认的Jackson行为反序列化对象 这是我目前掌握的密码 public class UserEventDeserializer extends StdDeserializer<User> { private static final long serialVersionUID = 7923585097068641765L; p

我在Jackson的自定义反序列化程序中遇到问题。我想访问默认序列化程序来填充我要反序列化的对象。在填充之后,我将执行一些自定义操作,但首先我想用默认的Jackson行为反序列化对象

这是我目前掌握的密码

public class UserEventDeserializer extends StdDeserializer<User> {

  private static final long serialVersionUID = 7923585097068641765L;

  public UserEventDeserializer() {
    super(User.class);
  }

  @Override
  @Transactional
  public User deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {

    ObjectCodec oc = jp.getCodec();
    JsonNode node = oc.readTree(jp);
    User deserializedUser = null;
    deserializedUser = super.deserialize(jp, ctxt, new User()); 
    // The previous line generates an exception java.lang.UnsupportedOperationException
    // Because there is no implementation of the deserializer.
    // I want a way to access the default spring deserializer for my User class.
    // How can I do that?

    //Special logic

    return deserializedUser;
  }

}
public类UserEventDeserializer扩展StdDeserializer{
私有静态最终长serialVersionUID=7923585097068641765L;
公共UserEventDeserializer(){
super(User.class);
}
@凌驾
@交易的
公共用户反序列化(JsonParser jp,反序列化上下文ctxt)
抛出IOException、JsonProcessingException{
ObjectCodec oc=jp.getCodec();
JsonNode=oc.readTree(jp);
用户反序列化duser=null;
反序列化(jp,ctxt,new User());
//前一行生成一个异常java.lang.UnsupportedOperationException
//因为没有反序列化器的实现。
//我想要一种方法来访问我的用户类的默认spring反序列化程序。
//我该怎么做?
//特殊逻辑
返回反序列化数据采集器;
}
}
我需要的是一种初始化默认反序列化程序的方法,以便在启动特殊逻辑之前可以预先填充POJO

当从自定义反序列化器中调用反序列化时,无论我如何构造序列化器类,该方法似乎都是从当前上下文调用的。因为我的POJO中的注释。这会导致堆栈溢出异常,原因很明显


我尝试过初始化
BeanDeserializer
,但过程非常复杂,我没有找到正确的方法。我还尝试过重载
AnnotationIntrospector
但没有效果,因为我认为这可能会帮助我忽略
反序列化上下文中的注释。最后,我可能已经在使用
JsonDeserializerBuilders
时取得了一些成功,尽管这需要我做一些神奇的事情来从Spring获得应用程序上下文。我将非常感谢任何能让我找到更干净的解决方案的事情,例如,我如何在不阅读
JsonDeserializer
注释的情况下构建反序列化上下文。

有两种方法可以做到这一点,但要正确地做到这一点需要做更多的工作。基本上,您不能使用子分类,因为默认反序列化程序需要的信息是从类定义构建的

因此,您最有可能使用的是构造一个
BeanDeserializerModifier
,通过
Module
接口注册它(使用
SimpleModule
)。您需要定义/覆盖
modifyDeserializer
,对于要添加自己的逻辑(类型匹配的地方)的特定情况,构建自己的反序列化程序,传递给定的默认反序列化程序。 然后在
deserialize()
方法中,您可以委托调用,获取结果对象

或者,如果必须实际创建和填充对象,则可以这样做并调用重载版本的
反序列化()
,该版本接受第三个参数;对象进行反序列化

另一种可能有效的方法(但不是100%确定)是指定
Converter
对象(
@JsonDeserialize(Converter=MyConverter.class)
)。这是Jackson 2.2的新功能。
在您的例子中,Converter实际上不会转换类型,而是简化修改对象:但我不知道这是否会让您完全按照您的要求执行,因为默认的反序列化程序将首先被调用,只有这样,您的
转换器才能像StaxMan建议的那样,通过编写
BeanDeserializerModifier
并通过
SimpleModule
注册它来实现这一点。以下示例应该有效:

public class UserEventDeserializer extends StdDeserializer<User> implements ResolvableDeserializer
{
  private static final long serialVersionUID = 7923585097068641765L;

  private final JsonDeserializer<?> defaultDeserializer;

  public UserEventDeserializer(JsonDeserializer<?> defaultDeserializer)
  {
    super(User.class);
    this.defaultDeserializer = defaultDeserializer;
  }

  @Override public User deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException
  {
    User deserializedUser = (User) defaultDeserializer.deserialize(jp, ctxt);

    // Special logic

    return deserializedUser;
  }

  // for some reason you have to implement ResolvableDeserializer when modifying BeanDeserializer
  // otherwise deserializing throws JsonMappingException??
  @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException
  {
    ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt);
  }


  public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException
  {
    SimpleModule module = new SimpleModule();
    module.setDeserializerModifier(new BeanDeserializerModifier()
    {
      @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer)
      {
        if (beanDesc.getBeanClass() == User.class)
          return new UserEventDeserializer(deserializer);
        return deserializer;
      }
    });


    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(module);
    User user = mapper.readValue(new File("test.json"), User.class);
  }
}
公共类UserEventDeserializer扩展STDESerializer实现ResolvableDeserializer
{
私有静态最终长serialVersionUID=7923585097068641765L;
私有最终JsonDeserializer defaultDeserializer;
公共UserEventDeserializer(JsonDeserializer defaultDeserializer)
{
super(User.class);
this.defaultDeserializer=defaultDeserializer;
}
@重写公共用户反序列化(JsonParser jp,反序列化上下文ctxt)
抛出IOException、JsonProcessingException
{
User deserializedUser=(用户)defaultDeserializer.deserialize(jp,ctxt);
//特殊逻辑
返回反序列化数据采集器;
}
//由于某些原因,在修改BeanDeserializer时必须实现ResolvableDeserializer
//否则反序列化会引发JsonMappingException??
@重写公共void resolve(反序列化上下文ctxt)引发JsonMappingException
{
((ResolvableDeserializer)defaultDeserializer).resolve(ctxt);
}
公共静态void main(字符串[]args)抛出JsonParseException、JsonMappingException、IOException
{
SimpleModule=新的SimpleModule();
module.setDeserializerModifier(新的BeanDeserializerModifier()
{
@重写公共JsonDeserializer modifyDeserializer(反序列化配置、BeanDescription BeanDeserializer、JsonDeserializer反序列化器)
{
if(beanDesc.getBeanClass()==User.class)
返回新的UserEventDeserializer(反序列化器);
返回反序列化器;
}
});
ObjectMapper mapper=新的ObjectMapper();
映射器注册表模块(模块);
User=mapper.readValue(新文件(“test.json”)、User.class);
}
}

我不同意使用
BeanSerializerModifier
,因为它强制在中央
ObjectMapper
中声明一些行为更改,而不是在自定义反序列化程序本身中,事实上,它是用
JsonSerialize
注释实体类的并行解决方案。如果您也有类似的感受,您可能会感激我在这里的回答:

对我来说,一个更简单的解决方案就是添加另一个
Ob bean
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.springframework.context.annotation.Bean;

import java.io.IOException;

public class IdWrapperDeserializer<T> extends StdDeserializer<T> {

    private Class<T> clazz;

    public IdWrapperDeserializer(Class<T> clazz) {
        super(clazz);
        this.clazz = clazz;
    }

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        return mapper;
    }

    @Override
    public T deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
        String json = jp.readValueAsTree().toString();
          // do your custom deserialization here using json
          // and decide when to use default deserialization using local objectMapper:
          T obj = objectMapper().readValue(json, clazz);

          return obj;
     }
}
@Bean
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
            mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
            mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
    SimpleModule testModule = new SimpleModule("MyModule")
            .addDeserializer(Category.class, new IdWrapperDeserializer(Category.class))

    mapper.registerModule(testModule);

    return mapper;
}
public User deserialize(JsonParser jp, DeserializationContext ctxt)
  throws IOException, JsonProcessingException {

    ObjectCodec oc = jp.getCodec();
    JsonNode node = oc.readTree(jp);
    User deserializedUser = null;

    DeserializationConfig config = ctxt.getConfig();
    JavaType type = TypeFactory.defaultInstance().constructType(User.class);
    JsonDeserializer<Object> defaultDeserializer = BeanDeserializerFactory.instance.buildBeanDeserializer(ctxt, type, config.introspect(type));

    if (defaultDeserializer instanceof ResolvableDeserializer) {
        ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt);
    }

    JsonParser treeParser = oc.treeAsTokens(node);
    config.initialize(treeParser);

    if (treeParser.getCurrentToken() == null) {
        treeParser.nextToken();
    }

    deserializedUser = (User) defaultDeserializer.deserialize(treeParser, context);

    return deserializedUser;
}
// your class
@JsonDeserialize(using = UserEventDeserializer.class)
public class User {
...
}

// extra user class
// reset deserializer attribute to default
@JsonDeserialize
public class UserPOJO extends User {
}

public class UserEventDeserializer extends StdDeserializer<User> {

  ...
  @Override
  public User deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {
    // specify UserPOJO.class to invoke default deserializer
    User deserializedUser = jp.ReadValueAs(UserPOJO.class);
    return deserializedUser;

    // or if you need to walk the JSON tree

    ObjectMapper mapper = (ObjectMapper) jp.getCodec();
    JsonNode node = oc.readTree(jp);
    // specify UserPOJO.class to invoke default deserializer
    User deserializedUser = mapper.treeToValue(node, UserPOJO.class);

    return deserializedUser;
  }

}
public class FooDeserializer extends StdDeserializer<FooBean> {

    private static final long serialVersionUID = 1L;

    public FooDeserializer() {
        this(null);
    }

    public FooDeserializer(Class<FooBean> t) {
        super(t);
    }

    @Override
    public FooBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        FooBean foo = new FooBean();
        foo.setBar(ctxt.readValue(node.get("bar").traverse(), BarBean.class));
        return foo;
    }

}
    public User deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
            User user = jp.readValueAs(User.class);
             // some code
             return user;
          }
public ObjectMapper getMapperWithCustomDeserializer() {
    ObjectMapper objectMapper = new ObjectMapper();

    SimpleModule module = new SimpleModule();
    module.setDeserializerModifier(new BeanDeserializerModifier() {
        @Override
        public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
                    BeanDescription beanDesc, JsonDeserializer<?> defaultDeserializer) 
            if (beanDesc.getBeanClass() == User.class) {
                return new UserEventDeserializer(defaultDeserializer);
            } else {
                return defaultDeserializer;
            }
        }
    });
    objectMapper.registerModule(module);

    return objectMapper;
}
public class UserEventDeserializer extends DelegatingDeserializer {

    public UserEventDeserializer(JsonDeserializer<?> delegate) {
        super(delegate);
    }

    @Override
    protected JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegate) {
        return new UserEventDeserializer(newDelegate);
    }

    @Override
    public User deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException {
        User result = (User) super.deserialize(p, ctxt);

        // add special logic here

        return result;
    }
}
public MyObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    MyObject object = new ObjectMapper().readValue(p, MyObject.class);
    // do whatever you want 
    return object;
}
ObjectMapper originalMapper = new ObjectMapper();
ObjectMapper copy = originalMapper.copy();//to keep original configuration
copy.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {

            @Override
            public Object findDeserializer(Annotated a) {
                Object deserializer = super.findDeserializer(a);
                if (deserializer == null) {
                    return null;
                }
                if (deserializer.equals(MyDeserializer.class)) {
                    return null;
                }
                return deserializer;
            }
});