2016-02-17 9 views
1

После попытки нескольких вариантов, я застрял в попытке сделать мой контроллер Spring HATEOAS полиморфизмом.Полиморфизм с весной Hateoas

Моим первым вариантом было реализовать ресурсы как экземпляры Resource, с моим объектом как content. Базовый класс определяется следующим образом:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") 
@JsonSubTypes({ @Type(value = Cat.class, name = "Cat"), @Type(value = Dog.class, name = "Dog") }) 
@JsonRootName("Animal") 
public abstract class Animal 
{ 
    : 
    : 
} 

При получении одного экземпляра или страницы, следующее исключение:

Could not write content: Unwrapped property requires use of type information: can not serialize without disabling `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS` 

полный репро доступен здесь: https://github.com/Bert-R/spring-hateoas-polymorphism/tree/master/src/main/java/nu/famroos/spring/hateoas/polymorphism/repro1

Мои что эта ошибка вызвана аннотацией @JsonUnwrapped по методу getContent от Resource. Очевидно, что PagedResources использует подобный подход.

Моя вторая попытка состояла в том, чтобы мои классы наследовали от ResourceSupport, чтобы обойти проблему @JsonUnwrapped. Базовый класс теперь выглядит так:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") 
@JsonSubTypes({ @Type(value = Cat2.class, name = "Cat2"), @Type(value = Dog2.class, name = "Dog2") }) 
@JsonRootName("Animal2") 
public abstract class Animal2 extends ResourceSupport 
{ 
    : 
    : 
} 

Это работает частично. Один ресурса теперь сериализовать правильно (обратите внимание на @type собственности):

{ 
    "@type":"Dog2", 
    "name":"nameofdog", 
    "barkVolume":1.0, 
    "_links":{ 
     "self":{ 
     "href":"http://localhost:8082/animals2/nameofdog" 
     } 
    } 
} 

Однако, страница не имеет @type свойства:

{ 
    "_embedded":{ 
     "Animal2s":[ 
     { 
      "name":"nameofdog", 
      "barkVolume":1.0, 
      "_links":{ 
       "self":{ 
        "href":"http://localhost:8082/animals2/nameofdog" 
       } 
      } 
     }, 
     : 
     : 
     ] 
    }, 
    "_links":{ 
     "self":{ 
     "href":"http://localhost:8082/animals2" 
     } 
    }, 
    "page":{ 
     "size":20, 
     "totalElements":3, 
     "totalPages":1, 
     "number":0 
    } 
} 

Код этой Repro доступен здесь: https://github.com/Bert-R/spring-hateoas-polymorphism/tree/master/src/main/java/nu/famroos/spring/hateoas/polymorphism/repro2

Я был бы очень признателен, если бы кто-нибудь мог объяснить, как заставить полиморфизм работать в сочетании с Spring HATEOAS.

ответ

1

Посмотрев дальше, я выяснил причину, почему атрибут @type не включен в страницу ресурсов: type erasure. См. this issue.

Существует обходное решение для этого: вместо include = JsonTypeInfo.As.PROPERTY используйте include = JsonTypeInfo.As.EXISTING_PROPERTY и добавьте свойство для каждого подкласса, который возвращает тип. Это не изящно, но позволяет реализовать полиморфный API. Полный исходный код этого обходного пути можно найти здесь: https://github.com/Bert-R/spring-hateoas-polymorphism/tree/master/src/main/java/nu/famroos/spring/hateoas/polymorphism/workaround

P.S. Для тех, кто считает, что отключение SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS решит проблему в первом варианте: если вы отключите этот параметр, информация о типе будет проигнорирована, поэтому атрибут @type не будет добавлен во время сериализации.

+0

Или просто создайте типизированный ресурс страницы. – zeroflagL

Смежные вопросы