我的实体:
public class User {
private Integer id;
private String mail;
private boolean enabled;
// getters and setters
}
文件test.json(从REST Web服务响应):
{
"_embedded" : {
"users" : [ {
"id" : 1,
"mail" : "[email protected]",
"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属性是唯一一人失踪(邮件和启用属性不为空)...
我有什么做的,解决这个问题?它是在杰克逊或Spring Jackson2HalModule一个错误?
您可以通过克隆我的弹簧HATEOAS叉repository和发射单元测试重现。
其实,这是由于它是建立包裹你的bean的内容Resource
类。内容属性被@JsonUnwrapped
注释,以便Resource
类可以在此属性,而在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);
它应该解决的问题。
有了这个代码,你会发现所有的@Entity豆的更改配置揭露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;
}
}
这为我工作:
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>>