Jackson ObjectMapper를 사용하여 슈퍼 클래스가 아닌 서브 클래스 이름을 JSON으로 직렬화합니다.

StackOverflow https://stackoverflow.com/questions/1325074

문제

객체를 JSON으로 직렬화하는 다음 Jackson/Java 코드에서 다음과 같습니다.

{"animal":{"x":"x"}}

그러나 내가 실제로 얻고 싶은 것은 다음과 같습니다.

{"dog":{"x":"x"}}

AnimalContainer에게 "동물"대신 물체의 런타임 유형 ( "개", "고양이")을 얻을 수 있도록 할 수있는 일이 있습니까? (편집하다: 지도 이름은 getter- 및 setter- 메소드 이름에서 나온다는 것을 알고 있습니다.) 내가 생각할 수있는 유일한 방법은 AnimalContainer 내에서 각 유형의 동물의 속성을 가지고 있고, 그들 모두를위한 세터와 getter를 가지고 있으며, 한 번에 하나만 가치가 있다는 것을 강요하는 것입니다. 그러나 이것은 동물 슈퍼 클래스를 갖는 목적을 물리 치고 그냥 틀린 것 같습니다. 그리고 내 실제 코드에는 실제로 "개"와 "고양이"뿐만 아니라 12 개의 서브 클래스가 있습니다. 이 작업을 수행하는 더 좋은 방법이 있습니까 (어쩌면 주석을 사용하여)? 필수화를위한 해결책도 필요합니다.

public class Test
{
   public static void main(String[] args) throws Exception
   {
      AnimalContainer animalContainer = new AnimalContainer();
      animalContainer.setAnimal(new Dog());

      StringWriter sw = new StringWriter();   // serialize
      ObjectMapper mapper = new ObjectMapper(); 
      MappingJsonFactory jsonFactory = new MappingJsonFactory();
      JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw);
      mapper.writeValue(jsonGenerator, animalContainer);
      sw.close();
      System.out.println(sw.getBuffer().toString());
   }
   public static class AnimalContainer
   {
      private Animal animal;
      public Animal getAnimal() {return animal;}
      public void setAnimal(Animal animal) {this.animal = animal;}
   }
   public abstract static class Animal 
   {
      String x = "x";
      public String getX() {return x;}
   }
   public static class Dog extends Animal {}
   public static class Cat extends Animal {} 
}
도움이 되었습니까?

해결책

에 따라 이 발표, Jackson 1.5는 전체 다형성 유형 처리를 구현하고 이제 트렁크는 해당 코드가 통합되었습니다.

이 작업을 수행하는 두 가지 간단한 방법이 있습니다.

  • SuperType (여기 동물)에 @jsontypeinfo 주석을 추가하거나
  • ObjectMapper.enabledeFaultTyping ()를 호출하여 Object Mapper를 구성합니다 (그렇다면 동물은 추상 유형이어야합니다)

다른 팁

이것은 아마도 당신이 찾고있는 대답이 아니지만 Jackson 버전 1.4 정도 (즉, 1.3, 1.3, 그 이후의 적절한 "다형성 사제화"(및 직렬화에 대한 필요한 지원)를 구현할 계획이 있습니다. 저것).

최신 버전의 경우 사용자 정의 직렬화/사막화기를 구현해야합니다. 아마도 사막화를위한 공장 메소드를 정의하고 Serializer 용 Getter ( 'getanimalticpe'또는 추상적 인 기본 클래스의 모든 것을 추상적, 하위 클래스로 무시하거나 무시합니다. 기본 클래스에서도 구현, 인스턴스 클래스의 출력 클래스 이름?).

어쨌든, 그것이 중요한 경우에, 여기에 JSON과의 하위 클래스 처리를 구현하는 데있어 근본적인 문제가 있으며 스키마 언어가 없다 (JSON은 실제로 널리 사용되지 않았기 때문에).

  • 데이터 (Bean 속성 값)를 메타 데이터와 분리하는 방법 (적절한 서브 클래스를 구성하는 데 필요한 유형 정보) - 별도로 유지해야하지만 형식은 정의 할 수있는 방법이 없으므로 JSON
  • 이러한 메타 데이터를 생성하고 사용하기 위해 적절한 주석을 추가하는 방법; 언어 별 기능에 의존하지 않고 (예 : Java 클래스 이름과 묶을 필요가 없어야 함)

이들은 해결할 수있는 문제이지만 사소하게 해결하기는 쉽지 않습니다. :-)

이것이 제가 생각할 수있는 유일한 방법이며 추악합니다. 더 좋은 방법이 있습니까?

   @JsonWriteNullProperties(false)
   public static class AnimalContainer
   {
      private Animal animal;

      public Animal getCat()
      {
         return animal instanceof Cat ? animal : null;
      }
      public void setCat(Cat cat)
      {
         this.animal = cat;
      }
      public Animal getDog()
      {
         return animal instanceof Dog ? animal : null;
      }
      public void setDog(Dog dog)
      {
         this.animal = dog;
      }
      public Animal getFish()
      {
         return animal instanceof Fish ? animal : null;
      }
      public void setFish(Fish fish)
      {
         this.animal = fish;
      }
   }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top