使用Jackson和Spring Hateoas的Jackson2HalModule反序列化json时的空id属性

mfa*_*ize 7 java hal jackson spring-data-rest spring-hateoas

我的实体:

public class User {

    private Integer id;
    private String mail;
    private boolean enabled;

    // getters and setters
}
Run Code Online (Sandbox Code Playgroud)

文件test.json(来自REST webservice的响应):

{
 "_embedded" : {
  "users" : [ {
    "id" : 1,
    "mail" : "admin@admin.com",
    "enabled" : true,
    "_links" : {
      "self" : {
        "href" : "http://localhost:8080/api/users/1"
      }
    }
  } ]
 }
}
Run Code Online (Sandbox Code Playgroud)

我的测试班:

public class TestJson {

    private InputStream is;
    private ObjectMapper mapper;

    @Before
    public void before() {
        mapper = new ObjectMapper();
        mapper.registerModule(new Jackson2HalModule());
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        is = TestJson.class.getResourceAsStream("/test.json");
    }

    @After
    public void after() throws IOException {
        is.close();
    }

    @Test
    public void test() throws IOException {
        PagedResources<Resource<User>> paged = mapper.readValue(is, new TypeReference<PagedResources<Resource<User>>>() {});
        Assert.assertNotNull(paged.getContent().iterator().next().getContent().getId());
    }

    @Test
    public void testResource() throws IOException {
        PagedResources<User> paged = mapper.readValue(is, new TypeReference<PagedResources<User>>() {});
        Assert.assertNotNull(paged.getContent().iterator().next().getId());
    }
}
Run Code Online (Sandbox Code Playgroud)

第二次测试通过但不是第一次.我不明白,因为用户中的id属性是唯一丢失的(邮件和启用的属性不为空)...

我该怎么做才能修复它?这是Jackson或Spring Jackson2HalModule中的一个错误吗?

您可以通过克隆我的spring-hateoas fork 存储库并启动单元测试来重现.

mfa*_*ize 10

实际上,这是由于为了Resource包装bean的内容而构建的类.content属性被注释,@JsonUnwrapped以便Resource类可以在此属性中映射您的bean,而在json中,bean属性与_linksproperty属性相同.使用此批注,可能会使包装器和内部bean的属性名称冲突.这正是这种情况,因为Resourceclass有一个idResourceSupport类继承的属性,并且这个属性很遗憾地被注释@JsonIgnore.

这个问题有一个解决方法.您可以创建MixIn从类继承的新类,ResourceSupportMixingetId()使用@JsonIgnore(false)注释覆盖该方法:

public abstract class IdResourceSupportMixin extends ResourceSupportMixin {

    @Override
    @JsonIgnore(false)
    public abstract Link getId();
}
Run Code Online (Sandbox Code Playgroud)

然后你只需要将你的IdResourceSupportMixin课程添加到你的ObjectMapper:

mapper.addMixInAnnotations(ResourceSupport.class, IdResourceSupportMixin.class);
Run Code Online (Sandbox Code Playgroud)

它应该解决问题.