잭슨이 있고 주석이 없는 다태적 반서열화

만약 내가 너에게 제목 사진의 여러 가지 선택 중에서 컵을 선택하라고 한다면, 당연히 너는 어느 것을 선택하느냐고 물어볼 것이다. 컵이 많기 때문에, 너는 정확하고 독특한 컵이 필요할 것이다.
모든 선택은 컵인데, 그것들은 약간의 공통점(색깔, 무게 등)이 있다.하지만 컵마다 다른 컵에 없는 것이 있을지도 모른다.이것은 다태성이다.
전체 소스 코드를 사용할 수 있습니다here.

무엇이 다태성입니까?


다태성은 하나의 인터페이스나 추상류가 서로 다른 실현 능력을 나타낸다.
이 글은 어떻게 추상적인 반서열화 대상을 통과하는지에 관한 것이다.아래에 소개한 같은 사상은 서열화 대상에 사용할 수 있다.
다음과 같은 추상적인 내용을 살펴보겠습니다.

추상적으로 여러 객체를 작성할 수 있는 POST 끝이 있다고 가정합니다.예를 들어 선수가 축구 선수, 테니스 선수 또는 농구 선수일 때 당신은 선수를 발표할 수 있다.
@PostMapping(value = "/players", consumes = MediaType.APPLICATION_JSON_VALUE)
  ResponseEntity<?> createPlayer(@RequestBody Player player);

문제


만약 우리가/players 단점을 직접 호출한다면, 우리는 InvalidDefinitionException에 직면하게 될 것이다. 왜냐하면 잭슨은 플레이어 요청 주체가 어떤 종류의 실례로 반서열화되어야 하는지를 정의할 수 없기 때문이다.

잭슨이 뭐예요?


제작자의 설명과 같이

Jackson has been known as "the Java JSON library" or "the best JSON parser for Java". Or simply as "JSON for Java".


간단하게 말하자면 잭슨은 JSON의 대상을 서열화하고 반서열화하는 Java 라이브러리이다.
이 문서에서는 Spring Boot을 사용하지만, 사용하지 않으려면 Jackson Databind Maven Central에 대한 최신 의존도를 얻으십시오.
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>VERSION_HERE</version>
</dependency>

반서열화


반서열화 부분은 반드시 JSON이 대표하는 구체적인 종류를 확정하고 그 실례를 실례화해야 한다.

주석 반서열화 사용


주석을 사용하는 것은 가장 자주 사용하는 기술일 수 있다. 왜냐하면 그것은 간단하고 시간을 절약하지만, 때로는 그것을 사용할 수 없기 때문이다.
일부 참고 자료는 이 점을 어떻게 하는지 설명합니다. 관심이 있으시면 here 또는 here 을 보실 수 있습니다.

주석이 없는 반서열화


모든 항목이 도메인 클래스에 주석을 추가할 수 있는 것은 아닙니다.
도메인 클래스(Player, FootballPlayer,...)가져온jar 의존 항목 뒤에 숨겼습니다. 주석에 접근할 수 없습니다.
또는
DDD 및 육각형 아키텍처를 사용하고 있습니다.

No framework or libraries inside the domain


또는
단지 당신 회사/프로젝트의 기술적 제한 때문일 뿐입니다.
우선 사용자 정의 잭슨 반서열화기를 만들고 반서열화 논리를 실현하는 것이다.
사용자 정의 반서열화기를 실현하기 위해서는 StdDeserializer의 실현을 만들어야 한다. 이것은 추상적인 유형으로 흔히 볼 수 있는 잭슨 반서열화기의 기류이다.
public class PlayerDeserializer extends StdDeserializer<Player> {

  public PlayerDeserializer() {
    this(null);
  }

  public PlayerDeserializer(final Class<?> vc) {
    super(vc);
  }

  @Override
  public Player deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
      throws IOException {
    // TODO - implement deserialization logic here
    return null;
  }
위의 몇 줄에서 우리는 플레이어에 대한 추상을 보여 주었다.서로 다른 플레이어의 실례를 구분하기 위해 매거를 만듭니다.
public enum SportType {

  FOOTBALL("FOOTBALL"),
  TENNIS("TENNIS"),
  BASKET("BASKET");

  private final String value;

  SportType(String value) {
    this.value = value;
  }

  @Override
  public String toString() {
    return String.valueOf(value);
  }

  public static SportType fromValue(String text) {
    for (SportType sportType : SportType.values()) {
      if (String.valueOf(sportType.value).equals(text)) {
        return sportType;
      }
    }
    return null;
  }
현재 우리는 SportType 매거를 정의했고 이를 바탕으로 deserialize 방법을 상세하게 실현할 수 있다.여기서 우리는 추상적인 플레이어의 sportType 필드를 이용할 수 있다.
@Override
  public Player deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
      throws IOException {

    final ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
    final JsonNode playerNode = mapper.readTree(jsonParser);

    final SportType sportType = SportType.fromValue(playerNode.get("sportType").asText());
    switch (sportType) {
      case FOOTBALL:
        return mapper.treeToValue(playerNode, FootballPlayer.class);
      case TENNIS:
        return mapper.treeToValue(playerNode, TennisPlayer.class);
      default:
        log.warn("Unexpected Player type : {}", sportType.toString());
        throw new IllegalStateException("Unexpected Player type : " + sportType.toString());
    }
  }
반서열화를 준비하기 전에 해야 할 마지막 단계는 우리PlayerDeserializer가 잭슨 서열화기/반서열화기의 일부라는 것을 지적하는 것이다.여기에는 두 가지 가능성이 있다.
  • 수동으로 등록PlayerDeserializer하고 ObjectMapper(소스 코드의 예)에 추가합니다.
  • 또는
  • Spring Boot을 사용할 때 사용할 수 있습니다 @JsonComponent. 같은 행동을 하지만 코드 줄이 더 적습니다.
  • 제목이'공짜 주석'을 표시하기 때문에 왜 우리가 이 주석을 가지고 있는지 물어보고 있을지도 모른다.@JsonComponent 스프링 부트 주석입니다. 잭슨의 일부가 아니라 새로 만든 반서열화기에 있습니다.
    또 다른 문제는 다음과 같습니다.

    What if we don't have this kind of "type" in our abstract class (e.g sportType) ?


    이런 상황에서 우리는 deserialize 방법을 약간 바꾸어 모든 유저의 실례 필드를 검사할 수 있다.
      @Override
      public Player deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
          throws IOException {
    
        final ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
        final JsonNode playerNode = mapper.readTree(jsonParser);
    
        final SportType sportType = SportType.fromValue(playerNode.get("sportType").asText());
    
        if (playerNode.has("position")) {
          return mapper.treeToValue(playerNode, FootballPlayer.class);
        }
        if (playerNode.has("atpPoints")) {
          return mapper.treeToValue(playerNode, TennisPlayer.class);
        }
        log.warn("Unexpected Player type : {}", sportType.toString());
        throw new IllegalStateException("Unexpected Player type : " + sportType.toString());
      }
    

    결론


    이 글에서, 우리는 사용자 정의 반서열화기를 사용하여 같은 단점에서 잭슨의 변수 요청(다태성)을 처리하고, 주석과 외부 라이브러리로 우리의 영역을 오염시키지 않는 방법을 배웠다.

    리소스


    소스 코드: https://github.com/redamessoudi/polymorphic-deserialization
    Eric Prouzet의 제목 사진

    좋은 웹페이지 즐겨찾기