如何删除Spring HATEOAS中的“_embedded”属性

dxxyhpgq  于 2023-02-16  发布在  Spring
关注(0)|答案(7)|浏览(203)

我正在使用Sping Boot 和HATEOAS构建REST API,当我的API返回一个集合时,它被 Package 在一个“_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"
            }
         }
      }
   ]
}

我的技术控制器:

@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;
    }

配置类具有注解@启用超媒体支持(类型=启用超媒体支持.超媒体类型.HAL)。
生成没有“_embedded”的响应的最佳方法是什么?

6ss1mwsb

6ss1mwsb1#

就像文件上说的
应用程序/hal+json响应应该被发送到接受应用程序/json的请求
为了在回答中省略_embedded,您需要添加

spring.hateoas.use-hal-as-default-json-media-type=false

application.properties

c7rzv4ha

c7rzv4ha2#

我关闭了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是很好的。

elcex8rz

elcex8rz3#

将此Accept标头添加到请求中:

Accept : application/x-spring-data-verbose+json
nszi6y05

nszi6y054#

对于那些使用Spring Data,并认为它是一个问题-解决方案是设置

spring.data.rest.defaultMediaType = application/json

在应用程序属性中。仍然有链接可用,但不再有_embedded。

eblbsuwk

eblbsuwk5#

你在生成结果和期望结果中描述的是语义上不同的东西,前者是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开始,ResourcesCollectionModelResourceEntityModel

yacmzcpb

yacmzcpb6#

您可以在服务中使用此代码

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[];
     }
   );
 }
jgzswidk

jgzswidk7#

对于Spring中的最新版本RepositoryRestConfigurer,不包括方法public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config),您需要覆盖RepositoryRestConfigurer上的默认方法,该方法包括cors参数。

public class RestConfiguration implements RepositoryRestConfigurer {

    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
        config.setDefaultMediaType(MediaType.APPLICATION_JSON);
        config.useHalAsDefaultJsonMediaType(false);
    }
}

相关问题