Когда я хочу десериализовать Entity с членом полиморфа, Джексон бросает com.fasterxml.jackson.databind.JsonMappingException
, жалуясь на отсутствующую информацию о типе (... которая фактически присутствует в примере JSON -> см. Пример) ,Jackson vs. Spring HATEOAS против полиморфизма
Unexpected token (END_OBJECT), expected FIELD_NAME: missing property '@class' that is to contain type id (for class demo.animal.Animal)\n at [Source: N/A; line: -1, column: -1] (through reference chain: demo.home.Home[\"pet\"])"
Все фактическая работа осуществляется с помощью PagingAndSortingRepository от Spring HATEOAS.
Я использую весеннюю загрузку V 1.2.4.RELEASE, что означает, что jackson - это V 2.4.6, а Spring HATEOAS - V 0.16.0.RELEASE.
Пример:
У меня есть домашнее животное дома:
@Entity
public class Home {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@OneToOne(cascade = {CascadeType.ALL})
private Animal pet;
public Animal getPet() {
return pet;
}
public void setPet(Animal pet) {
this.pet = pet;
}
}
Это Pet некоторые животных - в этом случае либо кошки или собаки. Это тип идентифицируется @class недвижимости ...
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public abstract class Animal {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
public class Cat extends Animal {
}
@Entity
public class Dog extends Animal {
}
Тогда это удобно PagingAndSortingRepository, что позволяет мне получить доступ в мой дом через REST/HATEOAS ...
@RepositoryRestResource(collectionResourceRel = "home", path = "home")
public interface HomeRepository extends PagingAndSortingRepository<Home, Integer> {
}
Чтобы подтвердить все что материал работает, у меня есть тест на месте ...
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
@WebAppConfiguration
public class HomeIntegrationTest {
@Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
@Before
public void setUp() {
this.mockMvc = webAppContextSetup(ctx).build();
}
@Test
public void testRename() throws Exception {
// I create my home with some cat...
// http://de.wikipedia.org/wiki/Schweizerdeutsch#Wortschatz -> Büsi
MockHttpServletRequestBuilder post = post("/home/")
.content("{\"pet\": {\"@class\": \"demo.animal.Cat\", \"name\": \"Büsi\"}}");
mockMvc.perform(post).andDo(print()).andExpect(status().isCreated());
// Confirm that the POST request works nicely, so the JSON thingy is correct...
MockHttpServletRequestBuilder get1 = get("/home/").accept(MediaType.APPLICATION_JSON);
mockMvc.perform(get1).andDo(print()).andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$._embedded.home", hasSize(1)))
.andExpect(jsonPath("$._embedded.home[0].pet.name", is("Büsi")));
// Now the interesting part: let's give that poor kitty a proper name...
MockHttpServletRequestBuilder put = put("/home/1")
.content("{\"pet\": {\"@class\": \"demo.animal.Cat\", \"name\": \"Beauford\"}}");
mockMvc.perform(put).andDo(print()).andExpect(status().isNoContent());
// PUT will thow JsonMappingException exception about an missing "@class"...
MockHttpServletRequestBuilder get2 = get("/home/").accept(MediaType.APPLICATION_JSON);
mockMvc.perform(get2).andDo(print()).andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$._embedded.home", hasSize(1)))
.andExpect(jsonPath("$._embedded.home[0].pet.name", is("Beaufort")));
}
}
Интересно, я могу создать свой дом с кошкой, как домашнее животное, но когда я хочу, чтобы обновить имя кошки не может десериализации J SON больше ...
Любые предложения?
Почему вы обновляете 'home', когда хотите изменить имя животного? Ваш 'put' создаст новое животное. – zeroflagL