REST API-API가 중첩 JSON 객체를 반환해야합니까?


37

JSON API와 관련하여 응답을 평평하게하고 중첩 된 JSON 객체를 피하는 것이 좋습니다.

예를 들어 IMDb와 유사하지만 비디오 게임용 API가 있다고 가정하겠습니다. 게임 및 플랫폼을 매핑하는 몇 가지 엔티티 인 Game, Platform, ESRBRating 및 GamePlatformMap이 있습니다.

/ game / 1을 요청하여 ID가 ​​1 인 게임을 가져오고 플랫폼과 esrbRating이 중첩 된 게임 객체를 반환한다고 가정 해 보겠습니다.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": [
    {"id":1,"name":"Xbox"},
    {"id":2,"name":"Playstation"}
  ],
  "esrbRating": {
    "id": 1,
    "code": "E",
    "name": "Everyone"
  }
}

JPA / Hibernate와 같은 것을 사용하는 경우 FETCH.EAGER로 설정된 경우 자동으로이를 수행 할 수 있습니다.

다른 옵션은 단순히 API를 작성하고 더 많은 엔드 포인트를 추가하는 것입니다.

이 경우 / game / 1이 요청되면 게임 오브젝트 만 반환됩니다.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
}

플랫폼 및 / 또는 ESRBRating을 원하면 다음을 호출해야합니다.

/ game / 1 / 플랫폼 / game / 1 / esrb

이 방법은 클라이언트가 필요로하는 데이터와 필요할 때에 따라 서버에 여러 번 더 호출 할 수있는 것처럼 보입니다.

당신이 이것과 같은 것을 가질 수있는 마지막 생각이있었습니다.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": ["Xbox","Playstation"]
}

그러나 이것은 ID 나 다른 플랫폼 정보와 관련된 정보가 필요하지 않다고 가정합니다.

API에서 반환 된 JSON 객체를 구성하는 가장 좋은 방법은 무엇인지 일반적으로 묻습니다. 가능한 한 엔터티에 가까이 접근해야합니까, 아니면 도메인 개체 또는 데이터 전송 개체를 사용하는 것이 좋습니다? 데이터 액세스 계층에 대한 더 많은 작업이나 클라이언트에 대한 더 많은 작업 중 하나의 방법으로 트레이드 오프가 발생한다는 것을 알고 있습니다.

또한 JPA / Hibernate 또는 MyBatis를 사용하여 API의 백엔드 기술로 Spring MVC를 사용하는 것과 관련된 답변을 듣고 싶습니다.


6
임베드 된 오브젝트를 리턴하는 경우 어떤 이의가 있습니까? 다른 엔드 포인트에서 개별적으로 내장 된 객체를 반환하면 상당히 성가 시게됩니다 (느리게 언급하지 않아도 됨).
— Robert Harvey

1
개인적으로 나는 이에 반대하지 않습니다. 모범 사례로 간주되는 사항을 알지 못합니다. 동료가 AngularJS에 포함 된 객체로 작업하는 것은 간단하지 않으며 결국에는 Ember of AngularJS 앱이 API를 소비하기를 원합니다. Angular 또는 Ember에 대해 영향을 줄지 여부를 알 수 없습니다.
— greyfox

3
답은 도메인 객체, DTO, ViewModel 객체 또는 KitchenSink 객체를 반환할지 여부에 따라 달라집니다. 어떤 객체를 반환하는지는 응용 프로그램의 요구 사항과 해당 객체가 인터넷을 통해 어떻게 동작하는지에 따라 결정될 가능성이 큽니다. 예 : 인보이스의 데이터로 웹 페이지를 채우려 고하는 경우 광고 항목 등에서 AJAXing을 계획하지 않는 한 필요한 모든 것을 포함하는 개체를 반환 할 가능성이 높습니다.
— Robert Harvey

이 경우 게임을 요청할 때 장르, 플랫폼 및 ESRBRating을 알고 싶을 것입니다. 말이 되네요 Java 관점에서의 디자인 측면에서 JPA 엔터티가있는 Entity 패키지와 비즈니스 오브젝트 / DTO 인 도메인 패키지가 사용자에게 리턴되도록하는 것이 좋습니다.
— greyfox

1
서버 호출 비용이 비쌉니다. 여러 호출을 사용하여 데이터를 보내야하는 API는 API가 필요없는 정보를 반환 할 때도 한 번의 호출로 모든 것을 가져올 수있는 API보다 느립니다.
— 로봇 고트

답변:


11

다른 대안 (HATEOAS 사용). 이것은 간단합니다. 대부분의 경우 실제로 HATEOAS 사용에 따라 json에 링크 태그를 추가합니다.

http://api.example.com/games/1:

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": [
    {"_self": "http://api.example.com/games/1/platforms/53", "name": "Playstation"},
    {"_self": "http://api.example.com/games/1/platforms/34", "name": "Xbox"},
  ]
}

http://api.example.com/games/1/platforms/34:

{
  "id": 34,
  "title": "Xbox",
  "publisher": "Microsoft",
  "releaseDate": "2015-01-01",
  "testReport": "http://api.example.com/games/1/platforms/34/reports/84848.pdf",
  "forms": [
    {"type": "edit", "fields: [] },
  ]
}

물론 모든 목록에 모든 데이터를 포함시킬 수는 있지만 너무 많은 데이터가 될 수 있습니다. 이 방법을 사용하면 필요한 데이터를 포함시킨 다음 실제로 작업하려는 경우 더 많은 데이터를로드 할 수 있습니다.

기술 구현에는 캐싱이 포함될 수 있습니다. 게임 오브젝트에 플랫폼 링크 및 이름을 캐시하고 플랫폼 API를 전혀로드하지 않고도 즉시 전송할 수 있습니다. 그런 다음 필요할 때로드 할 수 있습니다.

예를 들어 양식 정보를 추가 한 것을 알 수 있습니다. 게임 목록에로드하려는 것보다 자세한 json 객체에 훨씬 더 많은 정보가 있음을 보여주기 위해 그렇게했습니다.


상태가 없기 때문에 기술적으로 HATEOS라고 생각하지 않습니다.
— RibaldEddie

예,이 과정에 대한 정확한 단어는 확실하지 않습니다. 일반적으로 HATEOS는 나머지 API에서 연결하는 데 사용되지만 상태와 관련이 있음에 동의합니다. 구현 아이디어는 동일하지만. 다음은 예제에서 어떻게 사용할 수 있는지에 대한 약간의 내용입니다. stormpath.com/blog/linking-and-resource-expansion-rest-api-tips
— Luc Franken

그래도 좋은 생각입니다!
— RibaldEddie

1
클라이언트와 api 자체 (예 : 내부 api) 사이에 응집력이있는 API를 개발하는 경우 다른 리소스에 대한 링크를 제공하는 것보다 중첩 된 (또는 평탄화 된) 응답을 반환하는 것이 더 합리적 일 수 있습니다. 이는 더 많은 API 요청을 의미합니다 바람직하지 않을 수 있습니다.
— Bruno

@bruno 예. 그러나 제한이 있습니다. 더 큰 시스템에서는 모든 관련 개체를 모두 제공 할 수 없거나 원하지 않습니다. 기본적으로 포함하는 필드는 임의적이며 API 사용에 따라 선택할 수 있습니다. 따라서이 경우 수백 개의 필드가있는 플랫폼이있을 수 있으며 유스 케이스에는 플랫폼을 선택하기위한 선택 상자가 표시됩니다. 그런 다음 플랫폼 이름을 포함시키는 것이 합리적이지만 예를 들어 플랫폼의 재무 세부 정보는 필요하지 않습니다.
— Luc Franken

16

이것은 REST API 디자인과 관련하여 기본적인 질문 중 하나입니다. 모든 디자이너는 첫날에이 질문을합니다. 죄송하지만 답변은 "의존"입니다. 각 접근 방식에는 장단점이 있으며 결정을 내리고 진행하면됩니다.


10
이것은 전혀 도움이되지 않습니다. OP 자신도 "의지가 있으며 각 방법마다 장단점이 있습니다"를 알고있었습니다. 어떤 것이 의존하는지 또는 최소한 예를 들어 설명해야합니다.
— Pratik Singhal

5

https://www.slideshare.net/stormpath/rest-jsonapis에 제시된 접근 방식은 두 번째입니다.

즉, 중첩 된 자원을 상위 자원의 링크로 포함하는 한편 상위 엔드 포인트에서 확장 매개 변수를 제공하십시오.

제 생각에는 이것이 대부분의 경우 효율적이고 유연한 방법입니다.


2
나는이 접근법을 좋아한다. 궁금하신 분은 링크 된 슬라이드 쇼의 SLIDE 57에서 시작합니다.
— Adam Plocher
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.