Java Jackson自定义反序列化程序在Spring Boot中不工作

Java Jackson自定义反序列化程序在Spring Boot中不工作,java,spring-boot,jackson,json-deserialization,Java,Spring Boot,Jackson,Json Deserialization,我为我的实体创建了一个自定义反序列化程序,但它一直引发异常: 我有两个类:AppUser和AppUserAvatar AppUser.java @Entity @Table(name = "user") public class AppUser implements Serializable { @Transient private static final long serialVersionUID = -3536455219051825651L; @JsonPro

我为我的实体创建了一个自定义反序列化程序,但它一直引发异常:

我有两个类:AppUser和AppUserAvatar

AppUser.java

@Entity
@Table(name = "user")
public class AppUser implements Serializable {

    @Transient
    private static final long serialVersionUID = -3536455219051825651L;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    @Column(name = "password", nullable = false, length = 256)
    private String password;

    @JsonIgnore
    @Column(name = "is_active", nullable = false)
    private boolean active;

    @JsonIgnore
    @OneToMany(mappedBy = "appUser", targetEntity = AppUserAvatar.class, fetch = FetchType.LAZY)
    private List<AppUserAvatar> appUserAvatars;

    //// Getters and Setters and toString() ////
}
@Entity
@Table(name = "user_avatar")
public class AppUserAvatar extends BaseEntityD implements Serializable {

    @Transient
    private static final long serialVersionUID = 8992425872747011681L;

    @Column(name = "avatar", nullable = false)
    @Digits(integer = 20, fraction = 0)
    @NotEmpty
    private Long avatar;

    @JsonDeserialize(using = AppUserDeserializer.class)
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    private AppUser appUser;

    //// Getters and Setters and toString() ////
}
AppUserDeserializer.java 包com.nk.accountservice.deserializer

import com.edoctar.accountservice.config.exception.InputNotFoundException;
import com.edoctar.accountservice.domain.candidate.AppUser;
import com.edoctar.accountservice.service.candidate.AppUserService;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.io.Serializable;

public class AppUserDeserializer extends JsonDeserializer implements Serializable {

    private static final long serialVersionUID = -9012464195937554378L;

    private AppUserService appUserService;

    @Autowired
    public void setAppUserService(AppUserService appUserService) {
        this.appUserService = appUserService;
    }

    @Override
    public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        JsonNode node = jsonParser.getCodec().readTree(jsonParser);
        Long userId = node.asLong();
        System.out.println(node);
        System.out.println(node.asLong());
        AppUser appUser = appUserService.findById(userId);
        System.out.println("appuser: " + appUser);
        if (appUser == null) try {
            throw new InputNotFoundException("User not found!");
        } catch (InputNotFoundException e) {
            e.printStackTrace();
            return null;
        }

        return appUser;
    }
}
示例xhr男孩是:

{
  "appUser": 1,
  "avatar": 1
}
每次提交请求时都会引发异常

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.edoctar.accountservice.domain.candidate.AppUserAvatar["appUser"])]


我发现没有调用appUserService.findById()方法。我真的很困惑。我不知道我哪里出错了。对于任何解决方案都是非常有用的。谢谢。

更新答案: 无法使用自动连线属性,因为您不在Spring上下文中。您正在将类
AppUserDeserializer
作为注释中的引用传递

@JsonDeserialize(using = AppUserDeserializer.class)
在这种情况下,FasterJackson库创建了
AppUserDeserializer
的实例,因此不考虑
Autowired
注释

你可以用一个小技巧解决你的问题。在
AppUserService
中添加对spring创建的实例的静态引用:

 @Service
 public AppUserService {

   public static AppUserService instance;

   public AppUserService() {
     // Modify the constructor setting a static variable holding a
     // reference to the instance created by spring
     AppUserService.instance = this;
   }

   ...
 }
AppUserDeserializer
中使用该引用:

public class AppUserDeserializer extends JsonDeserializer implements Serializable {

    private AppUserService appUserService;

    public AppUserDeserializer() {
      // Set appUserService to the instance created by spring
      this.appUserService = AppUserService.instance;
    }

    ...

}

原始答案:要正确初始化
Autowired
属性,必须对类
AppUserDeserializer
进行注释,否则
appUserService
如果不使用set方法显式初始化,则为null

尝试使用
@Component
注释
AppUserDeserializer

@Component   // Add this annotation
public class AppUserDeserializer extends JsonDeserializer implements Serializable {
   ...
}

更新答案: 无法使用自动连线属性,因为您不在Spring上下文中。您正在将类
AppUserDeserializer
作为注释中的引用传递

@JsonDeserialize(using = AppUserDeserializer.class)
在这种情况下,FasterJackson库创建了
AppUserDeserializer
的实例,因此不考虑
Autowired
注释

你可以用一个小技巧解决你的问题。在
AppUserService
中添加对spring创建的实例的静态引用:

 @Service
 public AppUserService {

   public static AppUserService instance;

   public AppUserService() {
     // Modify the constructor setting a static variable holding a
     // reference to the instance created by spring
     AppUserService.instance = this;
   }

   ...
 }
AppUserDeserializer
中使用该引用:

public class AppUserDeserializer extends JsonDeserializer implements Serializable {

    private AppUserService appUserService;

    public AppUserDeserializer() {
      // Set appUserService to the instance created by spring
      this.appUserService = AppUserService.instance;
    }

    ...

}

原始答案:要正确初始化
Autowired
属性,必须对类
AppUserDeserializer
进行注释,否则
appUserService
如果不使用set方法显式初始化,则为null

尝试使用
@Component
注释
AppUserDeserializer

@Component   // Add this annotation
public class AppUserDeserializer extends JsonDeserializer implements Serializable {
   ...
}

尝试更改这行代码:

private boolean active;


布尔基元无法处理空值,可能导致NPE。

请尝试更改这行代码:

private boolean active;


布尔基元不能处理空值,可能导致NPE。

您可以继续并尝试正确注入
AppUserService
,但据我所知,这不是最干净的解决方案。通常我不喜欢使用
@Entity
作为通信模型或视图模型。通过这种方式,您将实体耦合到视图模型的生产者/消费者。您基本上是在使模型零件短路


我要做的是在反序列化阶段将json的内容映射到另一个类,然后使用这个类构造相应的实体

您可以继续并尝试正确注入
AppUserService
,但根据我的说法,这不是最干净的解决方案。通常我不喜欢使用
@Entity
作为通信模型或视图模型。通过这种方式,您将实体耦合到视图模型的生产者/消费者。您基本上是在使模型零件短路


我要做的是在反序列化阶段将json的内容映射到另一个类,然后使用这个类构造相应的实体

在反序列化程序中设置断点并查找
null
。我怀疑
appUserService
没有被注入,您得到了NPEthere@NiVeR下面是观察结果:
节点:“1”
appUserService=null
。我不知道为什么它是空的。我用
@service
注释了服务,我想我已经正确地注入了它。在反序列化程序中设置断点,然后找到
null
。我怀疑
appUserService
没有被注入,您得到了NPEthere@NiVeR下面是观察结果:
节点:“1”
appUserService=null
。我不知道为什么它是空的。我用
@service
注释了服务,我想我已经正确地注入了它。在用
@Component
注释了
AppUserDeserializer
之后,
appUserService
仍然为空;你在appUserService上有@Service吗?有<代码>org.springframework.stereotype.Service在服务上注释。我已将此appUserService bean注入到各种类中,没有问题。@byteHunt3r您是否正在创建AppUserDeserializer,并显式调用new AppUserDeserializer()?如果您这样做,那么您没有使用spring创建的实例,该实例已使用AppUserServiceI进行初始化。我直接将其与目标字段上的
@JsonDeserializer
一起使用。e、 g
@JsonDeserialize(using=AppUserDeserializer.class)
。在用
@Component
注释
AppUserDeserializer
后,
appUserService
仍然为空;你在appUserService上有@Service吗?有<代码>org.springframework.stereotype.Service在服务上注释。我已将此appUserService bean注入到各种类中,没有问题。@byteHunt3r您是否正在创建AppUserDeserializer,并显式调用new AppUserDeserializer()?如果您这样做,那么您没有使用spring创建的实例,该实例已使用AppUserServiceI进行初始化。我直接将其与目标字段上的
@JsonDeserializer
一起使用。e、 g
@JsonDeserialize(使用=AppUserDeserializer.class)
。在这种情况下,不确定这是否重要n