Пользовательский десериализатор Jackson не работает при загрузке весной - PullRequest
0 голосов
/ 07 декабря 2018

Я создал собственный десериализатор для своих сущностей, но он продолжает выдавать исключение:

У меня есть два класса: 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() ////
}

AppUserAvatar.java

@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 boy:

{
  "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"])]

Here's the screenshoot of my console.

Я обнаружил, что метод appUserService.findById () не вызывается.Я действительно смущен.Я не знаю, где я ошибся.Буду благодарен за любое решение.Спасибо.

Ответы [ 3 ]

0 голосов
/ 07 декабря 2018

Попробуйте изменить эту строку кода:

private boolean active;

на

private Boolean active;

логический примитив не может обрабатывать нули и может привести к NPE.

0 голосов
/ 07 декабря 2018

Вы можете продолжить и попытаться правильно ввести AppUserService, но, по моему мнению, это не самое чистое решение.Обычно мне не нравится идея использовать @Entity в качестве моделей связи или моделей просмотра.Таким образом, вы связываете сущность с производителем / потребителем модели представления.Вы в основном замыкаете часть модели.

Что я хотел бы сделать, это отобразить содержимое json на другой класс в фазе десериализации и использовать его позже для создания соответствующей сущности.

0 голосов
/ 07 декабря 2018

Обновленный ответ: Вы не можете использовать свойства автопроводки, поскольку находитесь вне контекста Spring.Вы передаете класс AppUserDeserializer в качестве ссылки в аннотации

@JsonDeserialize(using = AppUserDeserializer.class)

В этом случае библиотека FasterJackson создает экземпляр AppUserDeserializer, поэтому Autowiredаннотации не принимаются во внимание.

Вы можете решить свою проблему с помощью небольшого трюка.Добавьте статическую ссылку на экземпляр, созданный Spring, в AppUserService:

 @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.

Попробуйте аннотировать AppUserDeserializer с помощью @Component:

@Component   // Add this annotation
public class AppUserDeserializer extends JsonDeserializer implements Serializable {
   ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...