Los*_*ier 5 java polymorphism jackson spring-hateoas spring-boot
当我想用一个多态变量成员反序列化一个实体时,杰克逊抛出一个com.fasterxml.jackson.databind.JsonMappingException,抱怨缺少类型信息(...实际上存在于JSON中 - >参见示例).
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\"])"
Run Code Online (Sandbox Code Playgroud)
所有实际工作都由Spring HATEOAS的PagingAndSortingRepository完成.
我使用spring-boot 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;
}
}
Run Code Online (Sandbox Code Playgroud)
宠物是动物 - 在这种情况下是猫或狗.它的类型由@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 {
}
Run Code Online (Sandbox Code Playgroud)
然后有这个方便的PagingAndSortingRepository,它允许我通过REST/HATEOAS访问我的家...
@RepositoryRestResource(collectionResourceRel = "home", path = "home")
public interface HomeRepository extends PagingAndSortingRepository<Home, Integer> {
}
Run Code Online (Sandbox Code Playgroud)
为了确认所有这些东西都在工作,我有一个测试...
@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")));
}
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,我可以用猫作为宠物创建我的家,但是当我想要更新猫的名字时,它不能再反序列化JSON了...
有什么建议?
我将尝试一个半答案。
处理 PUT(也可能是 PATCH)时,spring-data-rest-webmvc将给定的 JSON 数据合并到现有实体中。这样做时,它会从 JSON 树中删除实体中不存在的所有属性,然后再将其传递给 Jackson ObjectMapper。换句话说,@class当杰克逊反序列化你的对象时,你的财产就消失了。
您可以通过将@class属性作为实际属性添加到实体中来解决此问题(出于测试/演示目的)(当然,您必须重命名它classname)。现在一切都会正常工作,但是您的实体现在拥有一个原本无用的classname属性,这可能不是您想要的。
由于类似的原因,使用该@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.WRAPPER_OBJECT)方法也行不通(除了这次整个包装对象被删除)。与原始方法一样,GET 和 POST 也可以正常工作。
整个事情看起来像是一个错误或@JsonTypeInfo不受支持的spring-data-rest-webmvc情况。
也许其他人可以对此有更多的了解。
| 归档时间: |
|
| 查看次数: |
691 次 |
| 最近记录: |