2009-04-07 1 views
3

컨텍스트에서는 대부분의 데이터를 JSON 문자열로 저장합니다. 이것은 백엔드의 Hadoop에서 잘 작동하며 프론트 엔드의 Ruby에서 처리하기 쉽습니다. 내 데이터 유형은 상속을위한 자연 패턴에 적합합니다.Java 및 Ruby를 사용하는 JSON에서의 다형성 또는 상속

간단히 말하면 애완 동물에게 먹이를주는 피드 Petet과 프로세스 Pet가 있다고 가정 해 보겠습니다. 나는 애완 동물의 종류 인 개에게만 적용되는 과정 WalkDog도 가지고 있습니다. 내 데이터는 개가 아닌 애완 동물을 걷는 것에 대해 걱정할 필요가 없도록 구성되었습니다.

애완 동물과 개가 애완 동물을 키우고 개가 "getLeash()"라는 추가 메서드가있는 것을 원합니다.하지만이를 JSON에 매핑하는 방법을 알 수는 없습니다.

대신 클래스 데이터 해시 맵이있는 클래스가 있으므로 WalkDog 프로세스는 dog.getLeash() 대신 pet.getSpeciesData ("가죽 끈")를 호출합니다.

Dog를 확장 할 수 있으며, Jackson 라이브러리를 사용하여 JSON에 직렬화 할 수 있습니다. JSON 객체에는 가죽 끈 필드가 있습니다. 그러나 나는 모든 애완 동물에게 먹이를주고 싶다고 가정한다. 모든 애완 동물에게는 getFood() 메소드가 있습니다. 따라서 FeedPet 프로세스는 개체를 Pet에 deserialize합니다. 그러나 이것은 끈 필드를 잃어 버린다.

WalkDog 프로세스는 모든 입력이 개가 될 것으로 알고 있기 때문에이를 수행 할 수 있으므로 Dog로 읽고 다시 Dog로 쓸 수 있습니다.

자바 객체를 JSON에 직렬화하여 형식을 유지할 수 있습니까? Rails의 단일 테이블 상속과 같은 것을 생각하고 있지만 JSON 라이브러리가 이해해야하는 부분이어야합니다.

답변

2

작동 시키려면 데이터에 일부 객체 유형 정보를 포함해야하며 (deserialize에만 유용함) 일반적으로 필요하지 않은 외부 스키마 정의를 사용해야합니다 (XML 스키마는 XML과 유사 함). 제네릭 타입 시스템). 이것은 ORM과 같은 문제를 가지고있다 : Hibernate는 추악한 work-arounds (n + 1-way 조인, "슈퍼 테이블"또는 discriminator 필드)를 사용해야한다.

또 다른 방법 : 데이터 매핑/바인딩은 객체 직렬화/직렬화 해제와 거의 같지 않습니다 (후자는 객체 식별을 더 많이 유지하려고합니다).여기

내가 당신이 원하는 것은 같은 기본적으로 가정하고이 경우가 아니라면

Pet pet = mapper.readValue(jsonString, Pet.class); 
// (and possibly get an exception if Pet is an abstract class...) 
Leash l = ((Dog) pet).getLeash(); 

, 당신은 단지 어쨌든 개

Dog dog = mapper.readValue(jsonString, Dog.class); 

에 바인딩 할 수 있습니다 : 잭슨 프로젝트 feature request for doing just this이 있는데, 당신이 원하는 것을 할 수있게 해줍니다.

그러나 JSON 내에서 객체 유형 정보를 전달하는 표준 방법이 없기 때문에이 솔루션은 대부분 Java에서 작동합니다. XML의 경우 이것은 "xsi : type"속성으로 정의 된 XML 스키마로 수행 할 수 있습니다. 이는 스키마 유형을 식별합니다. 그런 다음 클래스에 맵핑됩니다 (예, 다소 복잡한 방식이지만 작동합니다).

UPDATE는 : Jackson 1.5이 지원 (즉 잭슨-91 기능 요청을 구현)를 첨가하므로는 다형성 형태의 적절한 처리를 허용하는 유형의 식별자를 생성하기 위해 사용될 수있다. 또한 유형 정보가 포함되는 방법에 대한 세부 사항을 완벽하게 구성 할 수 있다면 비 Java 시스템에서도 작동해야합니다. Java 클래스 이름 사용에만 국한되지 않습니다.

+0

내가 핵심 부분에 답변했다고 생각합니다. JSON에서이를 표현하는 표준 방법이 없습니다. JACKSON-91은 제게 원하는 것을 정확히 제공 할 것입니다. 왜냐하면 제 경우에는 Ruby에서만 데이터를 읽고 있기 때문입니다. –

+0

아 좋아. 실제로, 당신이 자바로 그것을 읽어야 만한다면 91이 필요할 것이다. 클래스 정보를 쓰려면 더 쉬운 방법이있을 수 있습니다 (91에서도이 점을 분명히 설명 할 것입니다). 한 가지 방법은 Object.getClass()를 직렬화 가능하게 만드는 것입니다 (SerializationConfig.Feature.OUTPUT_CLASS_NAME?). – StaxMan

0

JSON을 장고에서 사용하는 것 이외에 다른 JSON을 사용 해본 적이별로 없지만 관련 값을 가진 "모델"키가 있습니다.

유형 및 상속 계층 구조를 결정하기 위해 개체를 해석하는 것은 프로그램에 달려 있습니다.

내가 말하고자하는 것은이 방법을 사용할 수 없다는 것입니다. 직렬화 할 필요가 없기 때문입니다. 객체의 이름과 속성 만.

- 프로세스가 아니라 실제 클래스보다 상위 클래스로 deserialising처럼 다시 질문을 읽고 나면 업데이트는

것 같습니다. 개 클래스가 애완 동물로부터 상속 받기 때문에, 당신은 당신의 디시리얼라이저가 가장 전문화 된 클래스의 객체를 생성하고 있는지 확인하기 만하면됩니다.

Jackson 라이브러리에 대해 잘 모르겠지만 모델 필드 유형을 설정하도록 설정하면 이동이 가능할 수 있습니다.