Configure HTTP and JSON for gRPC JSON transcoding
Note
This isn't the latest version of this article. For the current release, see the .NET 9 version of this article.
Warning
This version of ASP.NET Core is no longer supported. For more information, see .NET and .NET Core Support Policy. For the current release, see the .NET 8 version of this article.
Important
This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
For the current release, see the .NET 9 version of this article.
gRPC JSON transcoding creates RESTful JSON web APIs from gRPC methods. It uses annotations and options for customizing how a RESTful API maps to the gRPC methods.
HTTP rules
gRPC methods must be annotated with an HTTP rule before they support transcoding. The HTTP rule includes information about calling the gRPC method as a RESTful API, such as the HTTP method and route.
import "google/api/annotations.proto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/v1/greeter/{name}"
};
}
}
An HTTP rule is:
- An annotation on gRPC methods.
- Identified by the name
google.api.http
. - Imported from the
google/api/annotations.proto
file. Thegoogle/api/http.proto
andgoogle/api/annotations.proto
files need to be in the project.
Note
Documentation links to .NET reference source usually load the repository's default branch, which represents the current development for the next release of .NET. To select a tag for a specific release, use the Switch branches or tags dropdown list. For more information, see How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205).
HTTP method
The HTTP method is specified by setting the route to the matching HTTP method field name:
get
put
post
delete
patch
The custom
field allows for other HTTP methods.
In the following example, the CreateAddress
method is mapped to POST
with the specified route:
service Address {
rpc CreateAddress (CreateAddressRequest) returns (CreateAddressReply) {
option (google.api.http) = {
post: "/v1/address",
body: "*"
};
}
}
Route
gRPC JSON transcoding routes support route parameters. For example, {name}
in a route binds to the name
field on the request message.
To bind a field on a nested message, specify the path to the field. In the following example, {params.org}
binds to the org
field on the IssueParams
message:
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;
}
Transcoding routes and ASP.NET Core routes have a similar syntax and feature set. However, some ASP.NET Core routing features aren't supported by transcoding. These include:
Request body
Transcoding deserializes the request body JSON to the request message. The body
field specifies how the HTTP request body maps to the request message. The value is either the name of the request field whose value is mapped to the HTTP request body or *
for mapping all request fields.
In the following example, the HTTP request body is deserialized to the address
field:
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;
}
Query parameters
Any fields in the request message that aren't bound by route parameters or the request body can be set using HTTP query parameters.
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;
}
In the preceding example:
org
andrepo
fields are bound from route parameters.- Other fields, such as
text
and the nested fields frompage
, can be bound from the query string:?text=value&page.index=0&page.size=10
Response body
By default, transcoding serializes the entire response message as JSON. The response_body
field allows serialization of a subset of the response message.
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;
}
In the preceding example, the address
field is serialized to the response body as JSON.
Specification
For more information about customizing gRPC transcoding, see the HttpRule specification.
Customize JSON
Messages are converted to and from JSON using the JSON mapping in the Protobuf specification. Protobuf's JSON mapping is a standardized way to convert between JSON and Protobuf, and all serialization follows these rules.
However, gRPC JSON transcoding offers some limited options for customizing JSON with GrpcJsonSettings, as shown in the following table.
Option | Default Value | Description |
---|---|---|
IgnoreDefaultValues | false |
If set to true , fields with default values are ignored during serialization. |
WriteEnumsAsIntegers | false |
If set to true , enum values are written as integers instead of strings. |
WriteInt64sAsStrings | false |
If set to true , Int64 and UInt64 values are written as strings instead of numbers. |
WriteIndented | false |
If set to true , JSON is written using pretty printing. This option doesn't affect streaming methods, which write line-delimited JSON messages and can't use pretty printing. |
builder.Services.AddGrpc().AddJsonTranscoding(o =>
{
o.JsonSettings.WriteIndented = true;
});
In the .proto
file, the json_name
field option customizes a field's name when it's serialized as JSON, as in the following example:
message TestMessage {
string my_field = 1 [json_name="customFieldName"];
}
Transcoding doesn't support advanced JSON customization. Apps requiring precise JSON structure control should consider using ASP.NET Core Web API.
Additional resources
ASP.NET Core