私は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"
}
}
}
]
}
私の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)があります。
「_embedded」なしで応答を生成する最良の方法は何ですか?
documentation が言うように
application/hal + json応答は、application/jsonを受け入れるリクエストに送信する必要があります
応答で_embedded
を省略するには、追加する必要があります
spring.hateoas.use-hal-as-default-json-media-type=false
application.properties
へ。
このAccept
ヘッダーをリクエストに追加します:
Accept : application/x-spring-data-verbose+json
RestTemplateでResources/Resourceを使用するのは難しいので、HAL機能を閉じます。次のコードでこの機能を無効にします。
public class SpringRestConfiguration implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.setDefaultMediaType(MediaType.APPLICATION_JSON);
config.useHalAsDefaultJsonMediaType(false);
}
}
それは私のために働きます。 restTemplateでより多くのサポートがある場合、HALは適切です。
このコードをサービスで使用できます
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[];
}
);
}
Spring Dataを使用していて、それを問題と見なしている人のために-解決策は、
spring.data.rest.defaultMediaType = application/json
アプリケーションのプロパティ。リンクはまだ利用可能ですが、もう埋め込まれていません。
生成された結果と期待される結果で説明しているのは、意味的に異なるものです。前者はCollection<Technology>
のHAL表現です。後者は、次の表現です。
class Wrapper {
Resources<Technology> technologies;
}
これが、応答で表示したいトップレベルのtechnologies
プロパティを実際に作成する方法です。後者はコントローラーで作成しません。トップレベルのResources
instanceは基本的にはコレクションであり、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
isはEntityModel
です。