Cloud Endpoints 프레임워크 주석 및 구문

Endpoints 프레임워크 주석은 API 구성, 메소드, 매개변수, Endpoint의 속성과 동작을 정의하는 기타 중요한 세부정보를 설명합니다.

Maven 프로젝트를 사용하여 주석을 추가하는 방법에 대한 자세한 내용은 코드 작성 및 주석 추가를 참조하세요. Maven App Engine Cloud Endpoints 아티팩트는 백엔드 API를 생성 및 빌드하고 이를 사용하여 클라이언트 라이브러리를 생성할 수 있도록 제공됩니다.

전체 API의 구성과 동작을 지정하는 주석(API에 노출된 모든 클래스와 이러한 클래스의 노출된 모든 메서드에 영향을 줌)은 @Api입니다. @Api 주석이 있는 클래스의 공개, 비정적, 비브리지 메서드는 모두 공개 API에 노출됩니다.

특정 메서드를 위한 특수 API 구성이 필요한 경우 @ApiMethod를 사용하여 메서드별로 설정을 구성할 수 있습니다. 아래 표에 나열된 다양한 속성을 설정하여 이러한 주석을 구성합니다.

@Api: API-scoped annotations

주석 @Api는 전체 API를 구성하며 @ApiMethod에 의해 재정의되지 않는 한 클래스의 모든 공개 메서드에 적용됩니다.

API 내의 특정 클래스에 대해 지정된 @Api 주석을 재정의하려면 @ApiClass@ApiReference를 참조하세요.

필수 가져오기

이 기능을 사용하려면 다음 가져오기가 필요합니다.

import com.google.api.server.spi.config.Api;

속성

@Api 속성 설명
audiences API에 인증이 필요하고 Android 클라이언트를 지원하는 경우 필수 항목입니다. 자세한 내용은 클라이언트 ID 및 대상을 참조하세요. audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"}
apiKeyRequired 선택사항. Api 키를 제공하는 요청에 대한 액세스를 제한하는 데 사용됩니다. apiKeyRequired = AnnotationBoolean.TRUE
authenticators API가 Firebase, Auth0 또는 서비스 계정을 사용하여 인증하는 경우 필수 항목입니다. API가 Google ID 토큰을 사용하여 인증하는 경우에는 이 속성이 필요 없습니다. API 레벨 또는 개별 메서드 레벨에서 이 속성을 설정할 수 있습니다. {EspAuthenticator.class}로 설정하거나 인터페이스 인증자의 설명대로 따라 커스텀 인증자를 직접 작성할 수 있습니다. authenticators = {EspAuthenticator.class}
backendRoot 지원 중단되었습니다. 다른 경로에서 API를 제공하려면 web.xml 파일에서 EndpointsServlet 섹션의 url-pattern을 변경합니다. <url-pattern>/example-api/*</url-pattern>
canonicalName 클라이언트 라이브러리에서 API에 다른 이름이나 보다 읽기 쉬운 이름을 지정하는 데 사용됩니다. 이 이름은 클라이언트 라이브러리에서 이름을 생성하는 데 사용되며 백엔드 API는 name 속성에 지정된 값을 계속 사용합니다.

예를 들어 API에 dfaanalytics로 설정된 name이 있는 경우 이 속성을 사용하여 DFA Group Analytics의 표준 이름을 지정할 수 있습니다. 그러면 생성된 클라이언트 클래스에 DfaGroupAnalytics 이름이 포함됩니다.

이름 사이에 적절한 공백을 포함시켜야 합니다. 이러한 공백은 적절한 카멜표기법 또는 밑줄로 대체됩니다.
canonicalName = "DFA Analytics:"n
clientIds API에서 인증을 사용하는 경우 필수 항목입니다. 토큰을 요청할 수 있도록 허용된 클라이언트의 클라이언트 ID 목록입니다. 자세한 내용은 클라이언트 ID 및 대상을 참조하세요. clientIds = {"1-web-apps.apps.googleusercontent.com", "2-android-apps.apps.googleusercontent.com"}
defaultVersion version 속성에 아무것도 제공하지 않을 경우 기본 버전 사용 여부를 지정합니다. defaultVersion = AnnotationBoolean.TRUE
description API에 대한 간단한 설명으로, API를 설명하도록 검색 서비스에 노출되며 원할 경우 문서를 생성하는 데에도 사용할 수 있습니다. description = "Sample API for a simple game"
documentationLink 사용자가 이 버전의 API에 대한 문서를 찾을 수 있는 URL입니다. 사용자가 서비스를 알아볼 수 있도록 API 탐색기 페이지 맨 위에 '자세히 알아보기'로 강조표시됩니다. documentationLink = "http://link_to/docs"
issuers 커스텀 JWT 발급기관 구성입니다. issuers = { @ApiIssuer(name = "auth0", issuer = "https://test.auth0.com/authorize", jwksUri = "https://test.auth0.com/.well-known/jwks.json") }
issuerAudiences 개별 발급기관의 대상입니다. issuerAudiences = { @ApiIssuerAudience(name = "auth0", audiences = {"aud-1.auth0.com", "aud-2.auth0.com"}) }
limitDefinitions 선택사항. API의 할당량을 정의하는 데 사용됩니다. @ApiLimitMetric을 참조하세요. limitDefinitions = { @ApiLimitMetric(name = "read-requests", displayName = "Read requests", limit = 1000)}
name API의 모든 메서드 및 경로에 대한 프리픽스로 사용되는 API의 이름입니다. name 값은 다음과 같아야 합니다.
  • 반드시 소문자로 시작해야 합니다.
  • 반드시 정규 표현식 [a-z]+[A-Za-z0-9]*와 일치해야 합니다.
name 미지정 시 사용되는 기본값은 myapi입니다.
name = "foosBall"
namespace 생성된 클라이언트의 네임스페이스를 구성합니다. @ApiNamespace를 참조하세요. namespace=@ApiNamespace(ownerDomain="your-company.com", ownerName="YourCo", packagePath="cloud/platform")
root 지원 중단되었습니다. 다른 경로에서 API를 제공하려면 web.xml 파일에서 EndpointsServlet 섹션의 url-pattern을 변경합니다. <url-pattern>/example-api/*</url-pattern>
scopes 제공되지 않는 경우, 기본값은 OAuth에 필수인 이메일 범위(https://www.googleapis.com/auth/userinfo.email)입니다. 필요에 따라 이를 재정의하여 더 많은 OAuth 2.0 범위를 지정할 수 있습니다. 그러나 여러 범위를 정의하고 지정된 범위 중 하나라도 토큰이 발급된 경우 범위 검사에 통과합니다. 여러 범위를 요청하려면 각 범위 사이에 공백을 넣어 단일 String을 지정해야 합니다. 여기에서 특정 API 메서드에 지정된 범위를 재정의하려면 @ApiMethod 주석에 다른 범위를 지정합니다. scopes = {"ss0", "ss1 and_ss2"}
title API 탐색기에 API 제목으로 표시되고 검색 및 디렉터리 서비스에 노출되는 텍스트입니다. title = "My Backend API"
transformers 커스텀 변환기의 목록을 지정합니다. 이보다 더 나은 대체 주석(@ApiTransformer)이 있습니다. 이 속성은 @ApiTransformer에 의해 재정의됩니다. transformers = {BazTransformer.class}
version 엔드포인트 버전을 지정합니다. 미지정 시 사용되는 기본값은 v1입니다. version = "v2"

샘플@Api 주석

이 주석은 클래스 정의 앞에 위치합니다.

/** An endpoint class we are exposing. */
@Api(name = "myApi",
    version = "v1",
    namespace = @ApiNamespace(ownerDomain = "helloworld.example.com",
        ownerName = "helloworld.example.com",
        packagePath = ""))

고객 ID 및 대상

OAuth2 인증의 경우 특정 클라이언트 ID에 OAuth2 토큰이 발급되므로 클라이언트 ID를 사용하여 API에 대한 액세스를 제한할 수 있습니다. Google Cloud Console에서 Android 애플리케이션을 등록할 때 클라이언트 ID를 만듭니다. 이 클라이언트 ID가 인증을 위해 Google로부터 OAuth2 토큰을 요청하는 ID입니다. 백엔드 API가 인증으로 보호되면 OAuth2 액세스 토큰이 전송되어 Endpoints에서 열리고, 토큰에서 클라이언트 ID가 추출된 다음 백엔드의 선언된 허용 가능 클라이언트 ID 목록(clientIds 목록)과 비교됩니다.

Endpoints API에서 호출자를 인증하게 하려면 토큰을 요청하도록 허용된 clientIds 목록을 제공해야 합니다. 이 목록은 웹 또는 Android 클라이언트용으로 Google Cloud 콘솔을 통해 가져온 모든 클라이언트 ID로 구성되어야 합니다. 즉, API 빌드 시 클라이언트를 알고 있어야 합니다. 빈 목록({})을 지정하면 클라이언트가 인증으로 보호되는 메서드에 액세스할 수 없습니다.

clientIds 속성을 사용하는 상태에서 Google API 탐색기로 API에 대한 인증된 호출을 테스트하려면 clientIds 목록의 클라이언트 ID를 제공해야 하며 사용할 값은 com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID입니다.

대상 정보

clientIds 목록은 승인되지 않은 클라이언트로부터 백엔드 API를 보호합니다. 그러나 의도한 백엔드 API에만 인증 토큰이 작동하도록 클라이언트 보호를 강화해야 합니다. Android 클라이언트의 경우 이 메커니즘은 audiences 속성입니다. 이 속성에 백엔드 API의 클라이언트 ID를 지정합니다.

Google Cloud 콘솔 프로젝트를 만들 때 기본 클라이언트 ID가 자동으로 생성되고 프로젝트에서 사용할 수 있도록 이름이 지정됩니다. App Engine에 백엔드 API를 업로드하면 해당 클라이언트 ID가 사용됩니다. 이는 API 인증에 언급된 웹 클라이언트 ID입니다.

@ApiMethod: 메서드 범위 주석

주석 @ApiMethod@Api 또는 @ApiClass 주석에서 제공하는 기본값이 아닌 다른 API 구성을 제공하는 데 사용됩니다. 이는 선택사항입니다. @Api 주석이 있는 클래스의 모든 공개, 비정적, 비브리지 메서드는 @ApiMethod 주석 유무와 관계없이 API에 노출됩니다.

이 주석 내의 속성을 사용하면 단일 API 메서드의 세부정보를 구성할 수 있습니다. 같은 속성이 @Api@ApiMethod에 지정되면 @ApiMethod가 우선합니다.

필수 항목 가져오기

이 기능을 사용하려면 다음 가져오기가 필요합니다.

import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiMethod.HttpMethod;

속성

@ApiMethod 속성 설명
apiKeyRequired 선택사항. API 키를 제공하는 요청에 대한 액세스를 제한하는 데 사용됩니다. apiKeyRequired = AnnotationBoolean.TRUE
audiences @API에서 구성을 재정의하려면 이 속성을 제공합니다. 자세한 내용은 클라이언트 ID 및 대상을 참조하세요. audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"}
authenticators API가 Firebase, Auth0, 서비스 계정을 사용하여 인증하고 API 레벨에서 이 속성을 설정하지 않은 경우 필수 항목입니다. API가 Google ID 토큰을 사용하여 인증하는 경우에는 이 속성이 필요 없습니다. {EspAuthenticator.class}로 설정하거나 인터페이스 인증자의 설명대로 커스텀 인증자를 직접 작성할 수 있습니다. authenticators = {EspAuthenticator.class}
clientIds 토큰을 요청할 수 있도록 허용된 클라이언트의 클라이언트 ID 목록입니다. API에서 인증을 사용하는 경우 필수 항목입니다. clientIds = {"1-web-apps.apps.googleusercontent.com", "2-android-apps.apps.googleusercontent.com"}
httpMethod 사용할 HTTP 메소드입니다. 미설정 시 메서드 이름을 기준으로 기본값이 선택됩니다. httpMethod = HttpMethod.GET
issuerAudiences @Api에서 구성을 재정의하려면 이 속성을 제공합니다. issuerAudiences = { @ApiIssuerAudience(name = "auth0", audiences = {"aud-1.auth0.com", "aud-2.auth0.com"}) }
metricCosts 선택사항. 메서드에 할당량 한도가 있음을 나타냅니다. @ApiMetricCost 주석을 metricCosts에 할당합니다. limitDefinitions 속성도 지정하여 @Api 주석에 할당량을 정의해야 합니다. @ApiMetricCost 주석은 다음과 같은 속성을 사용합니다.
  • name: ApiLimitMetric 주석에 지정한 이름입니다.
  • cost: 각 요청의 비용을 지정하는 정수입니다. 비용은 메서드가 동일 할당량에서 서로 다른 속도로 소비할 수 있게 해 줍니다. 예를 들어 할당량의 한도가 1,000이고 cost가 1이면 호출하는 애플리케이션이 한도를 넘기 전에 분당 1,000개의 요청을 할 수 있습니다. 동일한 할당량에 대해 cost가 2인 경우 호출하는 애플리케이션이 한도를 넘기 전에 분당 500개의 요청만 할 수 있습니다.
metricCosts = { @ApiMetricCost(name = read-requests", cost = 1) }
name 생성된 클라이언트 라이브러리에서 이 메소드의 이름입니다. 여기에 자동으로 API 이름이 프리픽스로 붙어 메서드에 대한 고유한 이름이 만들어집니다. name 값은 다음과 같아야 합니다.
  • 반드시 소문자로 시작해야 합니다.
  • 반드시 정규 표현식 [a-z]+[A-Za-z0-9]*와 일치해야 합니다.
name 미지정 시 사용되는 기본값은 myapi입니다.
name = "foosBall.list"
path 이 메서드에 액세스하는 데 사용할 URI 경로입니다. 미설정 시 자바 메서드 이름을 기준으로 기본 경로가 사용됩니다. API 관리를 추가할 계획이면 경로에 후행 슬래시를 포함시키지 마세요. path = "foos"
scopes OAuth 2.0 범위를 한 개 이상 지정합니다. 이 범위 중 하나가 이 메서드를 호출하는 데 필요합니다. 메서드에 대해 scopes를 설정하면 이 설정 값이 @Api 주석의 설정을 재정의합니다. 여러 범위를 정의하고 지정된 범위 중 하나라도 토큰이 발급된 경우 범위 검사에 통과합니다. 여러 범위를 요청하려면 각 범위 사이에 공백을 넣어 단일 String을 지정하세요. scopes = {"ss0", "ss1 and_ss2"}

샘플 @ApiMethod 주석

이 주석은 클래스 내부의 메서드 정의 앞에 위치합니다.

/** A simple endpoint method that takes a name and says Hi back. */
@ApiMethod(
    name = "sayHiUser",
    httpMethod = ApiMethod.HttpMethod.GET)
public MyBean sayHiUser(@Named("name") String name, User user)
    throws OAuthRequestException, IOException {
  MyBean response = new MyBean();
  response.setData("Hi, " + name + "(" + user.getEmail() + ")");

  return response;
}

항목을 매개변수로 사용하는 메서드는 HttpMethod.POST(삽입 작업용) 또는 HttpMethod.PUT(업데이트 작업용)을 사용해야 합니다.

@ApiMethod(
    name = "mybean.insert",
    path = "mybean",
    httpMethod = ApiMethod.HttpMethod.POST
)
public void insertFoo(MyBean foo) {
}

@Named

@Named 주석은 서버 측 메서드에 전달되는 모든 비항목 유형 매개변수에 필요합니다. 이 주석은 여기에 삽입되는 요청에서 매개변수 이름을 나타냅니다. @Named 주석이 달리지 않은 매개변수는 전체 요청 객체와 함께 삽입됩니다.

필수 항목 가져오기

이 기능을 사용하려면 다음 가져오기가 필요합니다.

import javax.inject.Named;

이 샘플은 @Named 사용을 보여줍니다.

/** A simple endpoint method that takes a name and says Hi back. */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
  MyBean response = new MyBean();
  response.setData("Hi, " + name);

  return response;
}

여기서 @Named는 요청에 id 매개변수만 삽입되도록 지정합니다.

@ApiLimitMetric

이 섹션에서는 API의 할당량을 정의하는 데 필요한 주석을 설명합니다. 할당량 설정에 필요한 모든 단계는 할당량 구성을 참조하세요.

API 범위 주석limitDefinitions 속성에 @ApiLimitMetric 주석을 할당합니다. 또한 할당량을 적용하려는 각 메서드의 @ApiMethod 주석에 @ApiMetricCost를 추가해야 합니다.

필수 가져오기

이 기능을 사용하려면 다음 가져오기가 필요합니다.

import com.google.api.server.spi.config.ApiLimitMetric;

속성

@ApiLimitMetric 속성

설명
name 할당량의 이름입니다. 일반적으로 할당량을 고유하게 식별하는 요청 유형(예: 'read-requests' 또는 'write-requests')입니다.
displayName Google Cloud 콘솔의 Endpoints > 서비스 페이지의 할당량 탭에서 할당량을 식별할 수 있도록 표시되는 텍스트입니다. 이 텍스트는 IAM 및 관리자와 API 및 서비스의 할당량 페이지에 있는 API 소비자에게도 표시됩니다. 표시 이름은 최대 40자여야 합니다.
읽기 쉽게 할당량 페이지의 표시 이름에 'per minute per project'라는 텍스트가 자동으로 추가됩니다.
API의 소비자가 보는 할당량 페이지에 나열되는 Google 서비스의 표시 이름과 일관성을 유지하기 위해 표시 이름에 대해 다음이 권장됩니다.
  • 하나의 측정항목만 있을 때는 'Requests'를 사용합니다.
  • 여러 측정항목이 있을 때는 각 측정항목이 요청의 유형을 설명하고 'requests'라는 단어를 포함해야 합니다(예: 'Read requests' 또는 'Write requests').
  • 이 할당량의 비용이 1보다 크면 'requests' 대신 'quota units'를 사용합니다.
limit 할당량에 대한 소비자 프로젝트당 분당 최대 요청 수인 정수 값입니다.

limitDefinitions = {
      @ApiLimitMetric(
        name = "read-requests",
        displayName = "Read requests",
        limit = 1000),
      @ApiLimitMetric(
        name = "write-requests",
        displayName = "Write requests",
        limit = 50),
    }

@ApiNamespace

@ApiNamespace 주석을 사용하면 생성된 클라이언트 라이브러리가 클라이언트 라이브러리 생성 중 구성된 기본값이 아닌 사용자가 지정하는 네임스페이스를 갖게 됩니다.

기본적으로 이 주석을 사용하지 않을 경우 사용되는 네임스페이스는 your-project-id.appspot.com의 역입니다. 즉, 패키지 경로는 com.appspot.your-project-id.yourApi입니다.

@Api 주석 내에 @ApiNamespace 주석을 제공하여 기본 네임스페이스를 변경할 수 있습니다.

/** An endpoint class we are exposing. */
@Api(name = "myApi",
    version = "v1",
    namespace = @ApiNamespace(ownerDomain = "helloworld.example.com",
        ownerName = "helloworld.example.com",
        packagePath = ""))

ownerDomain 속성을 회사 도메인으로 설정하고 ownerName을 회사 이름으로 설정합니다(예: your-company.com). 그러면 ownerDomain의 역이 com.your-company.yourApi 패키지 경로에 사용됩니다.

필요에 따라 packagePath 속성을 사용하여 추가 범위를 제공할 수 있습니다. 예를 들어 packagePathcloud로 설정하면 com.your-company.cloud.yourApi가 클라이언트 라이브러리에 패키지 경로로 사용됩니다. / 구분 기호를 제공하여 패키지 경로에 더 많은 값을 추가할 수 있습니다(예: packagePath="cloud/platform").

@Nullable

이 주석은 메서드의 매개변수가 선택사항이므로 쿼리 매개변수임을 나타냅니다. @Nullable@Named 매개변수에만 사용할 수 있습니다.

@ApiClass

멀티클래스 API에서 @ApiClass를 사용하면 지정된 클래스에 다른 속성을 지정할 수 있습니다. 이는 @Api 구성에서 해당 속성을 재정의합니다. 이 주석에 대한 자세한 내용은 클래스 간 달라질 수 있는 속성에 @ApiClass 사용을 참조하세요.

@ApiReference

멀티클래스 API에서 @ApiReference를 사용하면 주석 상속의 대체 메서드를 제공할 수 있습니다. 이 주석에 대한 자세한 내용은 @ApiReference 상속 사용을 참조하세요.

@ApiResourceProperty

@ApiResourceProperty는 API에 리소스 속성이 노출되는 방식에 대한 제어를 제공합니다. 속성 getter 또는 setter에 이를 사용하여 API 리소스의 속성을 생략할 수 있습니다. 또한 필드가 비공개인 경우 필드 자체에 이를 사용하여 API에 이를 노출시킬 수 있습니다. 이 주석을 사용하여 API 리소스에서 속성 이름을 변경할 수도 있습니다.

필수 항목 가져오기

이 기능을 사용하려면 다음 가져오기가 필요합니다.

import com.google.api.server.spi.config.ApiResourceProperty;
import com.google.api.server.spi.config.AnnotationBoolean;

속성

@ApiResourceProperty 속성 설명
ignored AnnotationBoolean.TRUE로 설정된 경우 속성을 생략합니다. 지정하지 않거나 AnnotationBoolean.FALSE로 설정하면 속성이 생략되지 않습니다. @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
name 제공될 경우 API에 노출시킬 속성 이름을 지정합니다. @ApiResourceProperty(name = "baz")

@ApiResourceProperty를 사용한 샘플 클래스

다음 스니펫은 @ApiResourceProperty 주석이 달린 속성 getter가 있는 클래스를 보여줍니다.


class Resp {
  private String foobar = "foobar";
  private String bin = "bin";

  @ApiResourceProperty
  private String visible = "nothidden";

  @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
  public String getBin() {
    return bin;
  }

  public void setBin(String bin) {
    this.bin = bin;
  }

  @ApiResourceProperty(name = "baz")
  public String getFoobar() {
    return foobar;
  }

  public void setFoobar(String foobar) {
    this.foobar = foobar;
  }
}

public Resp getResp() {
  return new Resp();
}

앞의 코드 스니펫에서는 @ApiResourcePropertybin 속성의 getBin getter에 적용됩니다. 또한 ignored 속성 설정은 Endpoints Frameworks에 API 리소스의 이 속성을 무시하도록 지시합니다.

@ApiResourceProperty는 getter 또는 setter가 없는 비공개 필드 visible에도 적용됩니다. 이 주석을 사용하면 이 필드가 API 리소스의 속성으로 노출됩니다.

동일한 스니펫에서 @ApiResourcePropertyfoobar 속성 값을 반환하는 다른 getter인 getFoobar에도 적용됩니다. 이 주석의 name 속성은 Endpoints Frameworks에 API 리소스의 속성 이름을 변경하도록 지시합니다. 속성 값 자체는 변경되지 않습니다.

앞의 스니펫 예시에서 Resp 객체의 JSON 표현은 다음과 유사합니다.

{"baz": "foobar", "visible": "nothidden"}

@ApiTransformer

@ApiTransformer 주석은 다른 유형과의 변환을 통해 Endpoints에 유형이 노출되는 방식을 맞춤설정합니다. 지정된 변환기는 com.google.api.server.spi.config.Transformer의 구현이어야 합니다.

클래스에서 @ApiTransformer 주석을 사용하는 것이 변환기를 지정하는 가장 좋은 방법입니다. 그러나 @Api 주석의 transformer 속성에 커스텀 변환기를 지정할 수도 있습니다.

필수 항목 가져오기

이 기능을 사용하려면 다음 가져오기가 필요합니다.

import com.google.api.server.spi.config.ApiTransformer;

@ApiTransformer를 사용한 샘플 클래스

다음 스니펫은 @ApiTransformer 주석이 달린 클래스를 보여줍니다.


@ApiTransformer(BarTransformer.class)
public class Bar {
  private final int x;
  private final int y;

  public Bar(int x, int y) {
    this.x = x;
    this.y = y;
  }

  public int getX() {
    return x;
  }

  public int getY() {
    return y;
  }
}

이 클래스는 BarTransformer 클래스에 의해 변환됩니다.

샘플 Endpoints 변환기 클래스

다음 스니펫은 BarTransformer라는 샘플 변환기 클래스를 보여 줍니다. 이는 앞의 스니펫에서 @ApiTransformer가 참조하는 변환기입니다.

public class BarTransformer implements Transformer<Bar, String> {
  public String transformTo(Bar in) {
    return in.getX() + "," + in.getY();
  }

  public Bar transformFrom(String in) {
    String[] xy = in.split(",");
    return new Bar(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
  }
}

위의 변환기가 없으며 Bar 유형의 속성 bar를 가진 객체가 있는 경우 해당 객체는 다음과 같이 표현됩니다.

{"bar": {"x": 1, "y": 2}}

변환기가 있는 경우 객체는 다음과 같이 표현됩니다.

{"bar": "1,2"}