Package org.a2aproject.sdk.grpc.utils
Class JSONRPCUtils
java.lang.Object
org.a2aproject.sdk.grpc.utils.JSONRPCUtils
Utilities for converting between JSON-RPC 2.0 messages and Protocol Buffer objects.
This class provides a unified strategy for handling JSON-RPC requests and responses in the A2A SDK by bridging the JSON-RPC transport layer with Protocol Buffer-based internal representations.
Conversion Strategy
The conversion process follows a two-step approach:- JSON → Proto: JSON-RPC messages are parsed using Gson, then converted to Protocol Buffer
objects using Google's
JsonFormatparser. This ensures consistent handling of field names, types, and nested structures according to the proto3 specification. - Proto → Spec: Protocol Buffer objects are converted to A2A spec objects using
ProtoUtils.FromProtoconverters, which handle type mappings and create immutable spec-compliant Java objects.
Request Processing Flow
Incoming JSON-RPC Request ↓ parseRequestBody(String) Validate version, id, method ↓ parseMethodRequest() Parse params → Proto Builder ↓ ProtoUtils.FromProto.* Create JSONRPCRequest<?> with spec objects
Response Processing Flow
Incoming JSON-RPC Response ↓ parseResponseBody(String, String) Validate version, id, check for errors ↓ Parse result/error Proto Builder → spec objects ↓ ProtoUtils.FromProto.* Create JSONRPCResponse<?> with result or error
Serialization Flow
Proto MessageOrBuilder ↓ JsonFormat.printer() Proto JSON string ↓ Gson JsonWriter Complete JSON-RPC envelope
Error Handling
The class provides detailed error messages for common failure scenarios:- Missing/invalid method: Returns
MethodNotFoundErrorwith the invalid method name - Invalid parameters: Returns
InvalidParamsErrorwith proto parsing details - Protocol version mismatch: Returns
InvalidRequestErrorwith version info - Missing/invalid id: Returns
InvalidRequestErrorwith id validation details
Thread Safety
This class is thread-safe. All methods are stateless and use immutable shared resources (Gson instance is thread-safe, proto builders are created per-invocation).
Usage Example
// Parse incoming JSON-RPC request
String jsonRequest = """
{"jsonrpc":"2.0","id":1,"method":"tasks.get","params":{"name":"tasks/task-123"}}
""";
JSONRPCRequest<?> request = JSONRPCUtils.parseRequestBody(jsonRequest);
// Create JSON-RPC request from proto
org.a2aproject.sdk.grpc.GetTaskRequest protoRequest = ...;
String json = JSONRPCUtils.toJsonRPCRequest("req-1", "tasks.get", protoRequest);
// Create JSON-RPC response from proto
org.a2aproject.sdk.grpc.Task protoTask = ...;
String response = JSONRPCUtils.toJsonRPCResultResponse("req-1", protoTask);
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected static ObjectgetAndValidateId(com.google.gson.JsonObject jsonRpc) protected static StringgetAndValidateJsonrpc(com.google.gson.JsonObject jsonRpc) protected static ObjectgetIdIfPossible(com.google.gson.JsonObject jsonRpc) Try to get the request id if possible , returns "UNDETERMINED ID" otherwise.static A2AResponse<?>parseError(com.google.gson.JsonObject error, Object id, String method) static voidparseJsonString(String body, com.google.protobuf.Message.Builder builder, Object id) static voidparseJsonString(String body, com.google.protobuf.Message.Builder builder, Object id, boolean ignoringUnknownFields) protected static voidparseRequestBody(com.google.gson.JsonElement jsonRpc, com.google.protobuf.Message.Builder builder, Object id) static A2ARequest<?>parseRequestBody(String body, @Nullable String tenant) static A2AResponse<?>parseResponseBody(String body, String method) static StreamResponseparseResponseEvent(String body) static StringtoJsonRPCErrorResponse(@Nullable Object requestId, A2AError error) static StringtoJsonRPCRequest(@Nullable String requestId, String method, @Nullable com.google.protobuf.MessageOrBuilder payload) static StringtoJsonRPCResultResponse(@Nullable Object requestId, com.google.protobuf.MessageOrBuilder builder)
-
Constructor Details
-
JSONRPCUtils
public JSONRPCUtils()
-
-
Method Details
-
parseRequestBody
public static A2ARequest<?> parseRequestBody(String body, @Nullable String tenant) throws JsonMappingException, JsonProcessingException -
parseResponseEvent
public static StreamResponse parseResponseEvent(String body) throws JsonMappingException, JsonProcessingException -
parseResponseBody
public static A2AResponse<?> parseResponseBody(String body, String method) throws JsonMappingException, JsonProcessingException -
parseError
public static A2AResponse<?> parseError(com.google.gson.JsonObject error, Object id, String method) throws JsonMappingException - Throws:
JsonMappingException
-
parseRequestBody
protected static void parseRequestBody(com.google.gson.JsonElement jsonRpc, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException - Throws:
JsonProcessingException
-
parseJsonString
public static void parseJsonString(String body, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException - Throws:
JsonProcessingException
-
parseJsonString
public static void parseJsonString(String body, com.google.protobuf.Message.Builder builder, Object id, boolean ignoringUnknownFields) throws JsonProcessingException - Throws:
JsonProcessingException
-
getAndValidateJsonrpc
protected static String getAndValidateJsonrpc(com.google.gson.JsonObject jsonRpc) throws JsonMappingException - Throws:
JsonMappingException
-
getIdIfPossible
Try to get the request id if possible , returns "UNDETERMINED ID" otherwise. This should be only used for errors.- Parameters:
jsonRpc- the json rpc JSON.- Returns:
- the request id if possible , "UNDETERMINED ID" otherwise.
-
getAndValidateId
protected static Object getAndValidateId(com.google.gson.JsonObject jsonRpc) throws JsonMappingException - Throws:
JsonMappingException
-
toJsonRPCRequest
-
toJsonRPCResultResponse
-
toJsonRPCErrorResponse
-