Utilities for converting protocol buffer messages to and from JSON format, with configurable options and type registry support. This enables interoperability with JSON-based APIs and human-readable message representation in the shaded akka.protobufv3.internal.util package.
Main utility class providing JSON conversion functionality for protocol buffer messages.
/**
* Utility class to convert protobuf messages to/from JSON format.
* Provides configurable parsing and printing with custom type registries.
*/
class JsonFormat {
/** Create a JSON parser with default settings */
static Parser parser();
/** Create a JSON printer with default settings */
static Printer printer();
/** Create a type registry builder */
static TypeRegistry.Builder newBuilder();
/** Get empty type registry */
static TypeRegistry emptyTypeRegistry();
}Parses JSON representations into protocol buffer messages with configurable options.
/**
* Parser for converting JSON format to protocol buffer messages.
* Configurable with options for handling unknown fields and type resolution.
*/
static class JsonFormat.Parser {
/** Create parser that ignores unknown JSON fields */
Parser ignoringUnknownFields();
/** Create parser with custom type registry for Any message resolution */
Parser usingTypeRegistry(TypeRegistry registry);
/** Parse JSON string into message builder */
void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException;
/** Parse JSON from Readable into message builder */
void merge(Readable json, Message.Builder builder) throws InvalidProtocolBufferException;
/** Parse JSON string into message builder with extension registry */
void merge(String json, ExtensionRegistry extensionRegistry, Message.Builder builder)
throws InvalidProtocolBufferException;
/** Parse JSON from Readable with extension registry */
void merge(Readable json, ExtensionRegistry extensionRegistry, Message.Builder builder)
throws InvalidProtocolBufferException;
}Converts protocol buffer messages to JSON format with configurable output options.
/**
* Printer for converting protocol buffer messages to JSON format.
* Configurable with options for field naming and default value inclusion.
*/
static class JsonFormat.Printer {
/** Create printer that includes fields with default values */
Printer includingDefaultValueFields();
/** Create printer that preserves original proto field names */
Printer preservingProtoFieldNames();
/** Create printer that prints enums as integers instead of names */
Printer printingEnumsAsInts();
/** Create printer that omits whitespace for compact output */
Printer omittingInsignificantWhitespace();
/** Create printer with custom type registry for Any message resolution */
Printer usingTypeRegistry(TypeRegistry registry);
/** Convert message to JSON string */
String print(MessageOrBuilder message) throws InvalidProtocolBufferException;
/** Convert message to JSON and append to Appendable */
void appendTo(MessageOrBuilder message, Appendable output) throws IOException;
}Registry for resolving message types when parsing/printing Any messages in JSON format.
/**
* Registry for resolving message types when working with Any messages in JSON.
* Maps type URLs to message descriptors for dynamic type resolution.
*/
static class JsonFormat.TypeRegistry {
/** Find descriptor by type URL */
Descriptors.Descriptor find(String name);
/** Get all registered type URLs */
Set<String> getTypes();
/** Check if type is registered */
boolean contains(String typeUrl);
/** Get empty type registry */
static TypeRegistry getEmptyTypeRegistry();
/** Create a new type registry builder */
static Builder newBuilder();
/** Type registry builder */
static class Builder {
/** Add message type to registry */
Builder add(Descriptors.Descriptor messageType);
/** Add multiple message types to registry */
Builder add(Iterable<Descriptors.Descriptor> messageTypes);
/** Build the type registry */
TypeRegistry build();
}
}import akka.protobufv3.internal.util.JsonFormat;
// Convert message to JSON (assumes MyMessage exists)
// MyMessage message = MyMessage.newBuilder()
// .setName("John Doe")
// .setId(123)
// .setActive(true)
// .build();
// String json = JsonFormat.printer().print(message);
// System.out.println(json);
// Output: {"name":"John Doe","id":123,"active":true}
// Parse JSON back to message
String jsonInput = "{\"name\":\"Jane Doe\",\"id\":456,\"active\":false}";
// MyMessage.Builder builder = MyMessage.newBuilder();
// JsonFormat.parser().merge(jsonInput, builder);
// MyMessage parsed = builder.build();import akka.protobufv3.internal.util.JsonFormat;
// Create printer with custom options
JsonFormat.Printer printer = JsonFormat.printer()
.includingDefaultValueFields() // Include fields with default values
.preservingProtoFieldNames() // Use proto field names instead of JSON names
.printingEnumsAsInts() // Print enums as integers
.omittingInsignificantWhitespace(); // Compact output
// Convert message with custom printer
// String compactJson = printer.print(message);import akka.protobufv3.internal.util.JsonFormat;
// Create parser that ignores unknown fields
JsonFormat.Parser parser = JsonFormat.parser()
.ignoringUnknownFields();
// Parse JSON with unknown fields (they will be ignored)
String jsonWithExtra = "{\"name\":\"John\",\"id\":123,\"unknownField\":\"ignored\"}";
// MyMessage.Builder builder = MyMessage.newBuilder();
// parser.merge(jsonWithExtra, builder);
// MyMessage result = builder.build();import akka.protobufv3.internal.*;
import akka.protobufv3.internal.util.JsonFormat;
// Create type registry for Any message resolution
JsonFormat.TypeRegistry typeRegistry = JsonFormat.TypeRegistry.newBuilder()
// .add(MyMessage.getDescriptor())
// .add(AnotherMessage.getDescriptor())
.build();
// Create printer with type registry
JsonFormat.Printer printer = JsonFormat.printer()
.usingTypeRegistry(typeRegistry);
// Create parser with type registry
JsonFormat.Parser parser = JsonFormat.parser()
.usingTypeRegistry(typeRegistry);
// Work with Any messages containing registered types
// MyMessage originalMessage = MyMessage.newBuilder()
// .setName("example")
// .build();
// Any anyMessage = Any.pack(originalMessage);
// String json = printer.print(anyMessage);
//
// // Parse back
// Any.Builder anyBuilder = Any.newBuilder();
// parser.merge(json, anyBuilder);
// Any parsedAny = anyBuilder.build();
// MyMessage unpacked = parsedAny.unpack(MyMessage.class);import akka.protobufv3.internal.*;
import akka.protobufv3.internal.util.JsonFormat;
// Timestamp JSON conversion
Timestamp timestamp = Timestamp.newBuilder()
.setSeconds(1234567890)
.setNanos(123456789)
.build();
String timestampJson = JsonFormat.printer().print(timestamp);
// Output: "2009-02-13T23:31:30.123456789Z"
// Duration JSON conversion
Duration duration = Duration.newBuilder()
.setSeconds(300)
.setNanos(500000000)
.build();
String durationJson = JsonFormat.printer().print(duration);
// Output: "300.500s"
// Struct JSON conversion
Struct struct = Struct.newBuilder()
.putFields("name", Value.newBuilder()
.setStringValue("John")
.build())
.putFields("age", Value.newBuilder()
.setNumberValue(30)
.build())
.build();
String structJson = JsonFormat.printer().print(struct);
// Output: {"name":"John","age":30}import akka.protobufv3.internal.*;
import akka.protobufv3.internal.util.JsonFormat;
try {
// Attempt to parse invalid JSON
String invalidJson = "{invalid json}";
// MyMessage.Builder builder = MyMessage.newBuilder();
JsonFormat.parser().merge(invalidJson, builder);
} catch (InvalidProtocolBufferException e) {
System.err.println("JSON parsing failed: " + e.getMessage());
}
try {
// Attempt to print message with missing required fields
// MyMessage incompleteMessage = MyMessage.newBuilder().build();
// String json = JsonFormat.printer().print(incompleteMessage);
} catch (InvalidProtocolBufferException e) {
System.err.println("Message printing failed: " + e.getMessage());
}import akka.protobufv3.internal.*;
import akka.protobufv3.internal.util.JsonFormat;
import java.io.*;
// Read JSON from file
JsonFormat.Parser parser = JsonFormat.parser();
// MyMessage.Builder builder = MyMessage.newBuilder();
try (FileReader reader = new FileReader("message.json")) {
parser.merge(reader, builder);
// MyMessage message = builder.build();
} catch (IOException e) {
System.err.println("Failed to read JSON file: " + e.getMessage());
}
// Write JSON to file
JsonFormat.Printer printer = JsonFormat.printer()
.includingDefaultValueFields();
try (FileWriter writer = new FileWriter("output.json")) {
// printer.appendTo(message, writer);
} catch (IOException e) {
System.err.println("Failed to write JSON file: " + e.getMessage());
}import akka.protobufv3.internal.*;
import akka.protobufv3.internal.util.JsonFormat;
import java.io.*;
// Process multiple JSON messages from stream
JsonFormat.Parser parser = JsonFormat.parser().ignoringUnknownFields();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
if (!line.trim().isEmpty()) {
// MyMessage.Builder builder = MyMessage.newBuilder();
// parser.merge(line, builder);
// MyMessage message = builder.build();
// processMessage(message);
}
}
} catch (IOException e) {
System.err.println("Stream processing failed: " + e.getMessage());
}import akka.protobufv3.internal.util.JsonFormat;
// Default behavior: proto field names converted to JSON camelCase
// Proto field: user_name -> JSON field: userName
// Preserve original proto field names
JsonFormat.Printer preservingPrinter = JsonFormat.printer()
.preservingProtoFieldNames();
// Proto field: user_name -> JSON field: user_name
// String json = preservingPrinter.print(message);import akka.protobufv3.internal.util.JsonFormat;
// By default, fields with default values are omitted from JSON
// Include fields with default values
JsonFormat.Printer inclusivePrinter = JsonFormat.printer()
.includingDefaultValueFields();
// This will include fields like:
// - Empty strings: "field": ""
// - Zero numbers: "field": 0
// - False booleans: "field": false
// - Empty repeated fields: "field": []
// String jsonWithDefaults = inclusivePrinter.print(message);