Share via


為 gRPC JSON 轉碼設定 HTTP 和 JSON

作者:James Newton-King

gRPC JSON 轉碼可從 gRPC 方法建立 RESTful JSON Web API。 其使用註釋和選項來自訂 RESTful API 如何對應至 gRPC 方法。

HTTP 規則

gRPC 方法必須使用 HTTP 規則進行標註,才能支援轉碼。 HTTP 規則包含呼叫 gRPC 方法作為 RESTful API 的相關資訊,例如 HTTP 方法和路由。

import "google/api/annotations.proto";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

HTTP 規則為:

注意

.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤

HTTP 方法

將路由設定為相符的 HTTP 方法欄位名稱,藉以指定 HTTP 方法:

  • get
  • put
  • post
  • delete
  • patch

custom 欄位可用於其他 HTTP 方法。

在下列範例中,CreateAddress 方法使用指定的路由對應至 POST

service Address {
  rpc CreateAddress (CreateAddressRequest) returns (CreateAddressReply) {
    option (google.api.http) = {
      post: "/v1/address",
      body: "*"
    };
  }
}

路由

gRPC JSON 轉碼路由支援路由參數。 例如,路由中的 {name} 繫結至要求訊息上的 name 欄位。

若要繫結巢狀訊息上的欄位,請指定欄位的路徑。 在下列範例中,{params.org} 繫結至 IssueParams 訊息上的 org 欄位:

service Repository {
  rpc GetIssue (GetIssueRequest) returns (GetIssueReply) {
    option (google.api.http) = {
      get: "/{apiVersion}/{params.org}/{params.repo}/issue/{params.issueId}"
    };
  }
}

message GetIssueRequest {
  int32 api_version = 1;
  IssueParams params = 2;
}
message IssueParams {
  string org = 1;
  string repo = 2;
  int32 issueId = 3;
}

轉碼路由和 ASP.NET Core 路由具有類似的語法和功能集。 不過,轉碼不支援某些 ASP.NET Core 路由功能。 包括:

要求本文

轉碼會將要求本文 JSON 還原序列化為要求訊息。 body 欄位可指定 HTTP 要求本文對應至要求訊息的方式。 此值是其值對應至 HTTP 要求本文的要求欄位名稱,或用於對應所有要求欄位的 *

在下列範例中,HTTP 要求本文會還原序列化為 address 欄位:

service Address {
  rpc AddAddress (AddAddressRequest) returns (AddAddressReply) {
    option (google.api.http) = {
      post: "/{apiVersion}/address",
      body: "address"
    };
  }
}

message AddAddressRequest {
  int32 api_version = 1;
  Address address = 2;
}
message Address {
  string street = 1;
  string city = 2;
  string country = 3;
}

查詢參數

要求訊息中未透過路由參數或要求本文繫結的任何欄位都可以使用 HTTP 查詢參數來設定。

service Repository {
  rpc GetIssues (GetIssuesRequest) returns (GetIssuesReply) {
    option (google.api.http) = {
      get: "/v1/{org}/{repo}/issue"
    };
  }
}

message GetIssuesRequest {
  string org = 1;
  string repo = 2;
  string text = 3;
  PageParams page = 4;
}
message PageParams {
  int32 index = 1;
  int32 size = 2;
}

在前述範例中:

  • orgrepo 欄位是從路由參數繫結。
  • 其他欄位 (例如 textpage 中的巢狀欄位) 可以從查詢字串繫結:?text=value&page.index=0&page.size=10

回應本文

根據預設,轉碼會將整個回應訊息序列化為 JSON。 response_body 欄位允許序列化回應訊息的子集。

service Address {
  rpc GetAddress (GetAddressRequest) returns (GetAddressReply) {
    option (google.api.http) = {
      get: "/v1/address/{id}",
      response_body: "address"
    };
  }
}

message GetAddressReply {
  int32 version = 1;
  Address address = 2;
}
message Address {
  string street = 1;
  string city = 2;
  string country = 3;
}

在上述範例中,address 欄位會作為 JSON 序列化為回應本文。

規格

如需自訂 gRPC 轉碼的詳細資訊,請參閱 HttpRule 規格

自訂 JSON

使用 Protobuf 規格中的 JSON 對應在訊息與 JSON 之間轉換。 Protobuf 的 JSON 對應是一種在 JSON 與 Protobuf 之間轉換的標準化方式,所有序列化都會遵循這些規則。

不過,gRPC JSON 轉碼提供一些使用 GrpcJsonSettings 自訂 JSON 的有限選項,如下表所示。

選項 預設值 說明
IgnoreDefaultValues false 如果設定為 true,則會在序列化期間忽略具有預設值的欄位。
WriteEnumsAsIntegers false 如果設定為 true,則列舉值會寫入為整數,而不是字串。
WriteInt64sAsStrings false 如果設定為 true,則 Int64UInt64 值會寫入為字串,而不是數字。
WriteIndented false 如果設定為 true,則會使用美化顯示來寫入 JSON。 此選項不會影響串流方法,該方法會寫入以行分隔的 JSON 訊息,而且無法使用美化顯示。
builder.Services.AddGrpc().AddJsonTranscoding(o =>
{
    o.JsonSettings.WriteIndented = true;
});

.proto 檔案中,json_name 欄位選項會在其序列化為 JSON 時自訂欄位名稱,如下列範例所示:

message TestMessage {
  string my_field = 1 [json_name="customFieldName"];
}

轉碼不支援進階 JSON 自訂。 需要精確 JSON 結構控制的應用程式應考慮使用 ASP.NET Core Web API

其他資源