Khi tôi muốn deserialize một thực thể với một thành viên đa hình, Jackson ném một com.fasterxml.jackson.databind.JsonMappingException
, phàn nàn về một loại thông tin bị thiếu (... mà thực sự hiện diện trong JSON -> xem ví dụ) .Jackson so với mùa xuân HATEOAS so với đa hình
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\"])"
Tất cả công việc thực tế được thực hiện bởi PagingAndSortingRepository từ Spring HATEOAS.
Tôi sử dụng khởi động mùa xuân V 1.2.4.RELEASE, có nghĩa là jackson là V 2.4.6 và Spring HATEOAS là V 0.16.0.RELEASE.
Ví dụ:
Tôi có một con vật cưng ở nhà:
@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 là một số động vật - trong trường hợp này hoặc là một Cát hoặc một Dog. Nó loại được xác định bởi thuộc tính @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 {
}
Tiếp theo là PagingAndSortingRepository này tiện dụng, cho phép tôi tiếp cận nhà của tôi qua REST/HATEOAS ...
@RepositoryRestResource(collectionResourceRel = "home", path = "home")
public interface HomeRepository extends PagingAndSortingRepository<Home, Integer> {
}
Để xác nhận tất cả công cụ đó đang hoạt động, tôi có một thử nghiệm tại chỗ ...
@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")));
}
}
Thú vị tôi có thể tạo ngôi nhà của mình với mèo làm vật nuôi, nhưng khi tôi muốn cập nhật tên của con mèo, nó không thể deserialize J SON nữa ...
Bất kỳ đề xuất nào?
Tại sao bạn cập nhật 'nhà riêng' khi bạn muốn thay đổi tên của động vật? 'Put' của bạn sẽ tạo ra một con vật mới. – zeroflagL