我使用Spring Boot和HATEOAS构建REST API,当我的API返回一个集合时,它被包装在一个" _embedded"财产,像这样:
{
"_links":{
"self":{
"href":"http://localhost:8080/technologies"
}
},
"_embedded":{
"technologies":[
{
"id":1,
"description":"A",
"_links":{
"self":{
"href":"http://localhost:8080/technologies/1"
}
}
},
{
"id":2,
"description":"B",
"_links":{
"self":{
"href":"http://localhost:8080/technologies/2"
}
}
}
]
}
}
我希望回复是这样的:
{
"_links":{
"self":{
"href":"http://localhost:8080/technologies"
}
},
"technologies":[
{
"id":1,
"description":"A",
"_links":{
"self":{
"href":"http://localhost:8080/technologies/1"
}
}
},
{
"id":2,
"description":"B",
"_links":{
"self":{
"href":"http://localhost:8080/technologies/2"
}
}
}
]
}
My TechnologiesController:
@RestController
@ExposesResourceFor(Technology.class)
@RequestMapping(value = "/technologies")
public class TechnologiesController {
...
@ResquestMapping(method = RequestMethod.GET, produces = "application/vnd.xpto-technologies.text+json")
public Resources<Resource<Technology>> getAllTechnologies() {
List<Technology> technologies = technologyGateway.getAllTechnologies();
Resources<<Resource<Technology>> resources = new Resources<Resource<Technology>>(technologyResourceAssembler.toResources(technologies));
resources.add(linkTo(methodOn(TechnologiesController.class).getAllTechnologies()).withSelfRel());
return resources;
}
配置类具有注释@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)。
没有&#34; _embedded&#34;产生响应的最佳方法是什么?
答案 0 :(得分:8)
正如documentation所说
application / hal + json响应应发送给接受的请求 应用/ JSON
为了在您的回复中省略_embedded
,您需要添加
spring.hateoas.use-hal-as-default-json-media-type=false
到application.properties
。
答案 1 :(得分:6)
将此Accept
标头添加到请求中:
Accept : application/x-spring-data-verbose+json
答案 2 :(得分:3)
我关闭了HAL功能,因为用restTemplate很难使用Resources / Resource。我通过以下代码禁用此功能:
public class SpringRestConfiguration implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.setDefaultMediaType(MediaType.APPLICATION_JSON);
config.useHalAsDefaultJsonMediaType(false);
}
}
对我有用。如果restTemplate有更多支持,则HAL很好。
答案 3 :(得分:2)
在产生的结果和预期的结果中所描述的是语义上不同的事物。前一件事是Collection<Technology>
的HAL表示形式。您希望后者是:
class Wrapper {
Resources<Technology> technologies;
}
请注意,这是我们实际上如何创建您希望在响应中看到的顶级technologies
属性的方式。您无需在控制器中创建任何后者。顶级Resources
实例基本上是一个集合,在HAL中表示顶级集合的唯一方法是_embedded
。显然您不希望那样做,但这就是您在控制器方法中编写的内容。
假设您拥有Wrapper
,则类似的事情应该起作用(未经测试):
Wrapper wrapper = new Wrapper(assembler.toCollectionModel(technologies);
EntityModel<Wrapper> model = EntityModel.of(wrapper);
model.add(linkTo(…));
PS:从Spring HATEOAS 1.0开始,Resources
是CollectionModel
,而Resource
是EntityModel
。
答案 4 :(得分:1)
您可以在服务中使用此代码
constructor(
private httpClient: HttpClient
) { }
retrieveAllStudents(){
return this.httpClient.get<any[]>(`http://localhost:8080/students`);
}
这将处理Json的_embedded部分并提取所需的数据。
export class ListStudentsComponent implements OnInit {
// declaring variables to be used
student: Student;
students: Student[];
message: string;
// injecting student service into the constuctor
constructor(
private studentService: StudentService,
) { }
ngOnInit() {
this.refreshStudents();
}
refreshStudents(){
this.studentService.retrieveAllStudents().subscribe(
response => {
console.log(response);
this.students = response._embedded.students as Student[];
}
);
}
答案 5 :(得分:0)
让那些使用Spring Data的人感到烦恼,并将其视为问题-解决方案是设置
spring.data.rest.defaultMediaType = application/json
在复制属性中。仍然会有链接,但是不再嵌入。