9

我的实体:

public class User {

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

    // getters and setters
}

文件 test.json(来自 REST 网络服务的响应):

{
 "_embedded" : {
  "users" : [ {
    "id" : 1,
    "mail" : "admin@admin.com",
    "enabled" : true,
    "_links" : {
      "self" : {
        "href" : "http://localhost:8080/api/users/1"
      }
    }
  } ]
 }
}

我的测试课:

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());
    }
}

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

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

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

4

3 回答 3

13

实际上,这是由于Resource构建用于包装 bean 内容的类。content 属性被注解,@JsonUnwrapped以便Resource类可以在此属性中映射您的 bean,而在 json 中,bean 属性与属性处于同一级别_links。使用此注解,可能与包装器和内部 bean 发生属性名称冲突。这正是这里的情况,因为Resource类有一个id从类继承的属性ResourceSupport,而这个属性不幸地被注释了@JsonIgnore

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

public abstract class IdResourceSupportMixin extends ResourceSupportMixin {

    @Override
    @JsonIgnore(false)
    public abstract Link getId();
}

然后您只需将您的IdResourceSupportMixin课程添加到您的ObjectMapper

mapper.addMixInAnnotations(ResourceSupport.class, IdResourceSupportMixin.class);

它应该可以解决问题。

于 2015-06-12T20:23:24.700 回答
1

使用此代码,您可以找到所有 @Entity bean 并更改配置以公开 Id 值:

 import java.util.LinkedList;
 import java.util.List;

 import javax.persistence.Entity;

 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
 import org.springframework.core.type.filter.AnnotationTypeFilter;
 import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
 import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
 import org.springframework.stereotype.Component;

 import com.rvillalba.exampleApiHateoas.entity.Example;

 import lombok.extern.slf4j.Slf4j;

 @Component
 @Slf4j
 public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter {

     @Override
     public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
         listMatchingClasses(Entity.class).forEach(entity -> config.exposeIdsFor(entity));
     }

     public List<Class> listMatchingClasses(Class annotationClass) {
         List<Class> classes = new LinkedList<Class>();
         ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true);
         scanner.addIncludeFilter(new AnnotationTypeFilter(annotationClass));
         for (BeanDefinition bd : scanner.findCandidateComponents(Example.class.getPackage().getName())) {
             try {
                 classes.add(Class.forName(bd.getBeanClassName()));
             } catch (ClassNotFoundException e) {
                 log.error("listMatchingClasses problem", e);
             }
         }
         return classes;
     }

 }
于 2017-04-10T15:36:04.487 回答
0

这对我有用:

public class User extends ResourceSupport {

    @JsonIgnore(false)
    private Integer id;
    private String mail;
    private boolean enabled;

    // getters and setters
}

另外,将您的http客户更改为返回PagedResources <User>而不是PagedResources<Resource<User>>

于 2016-12-23T17:00:28.067 回答