Akka Protobuf V3 is a shaded version of the Google protobuf runtime library that renames com.google.protobuf.** to akka.protobufv3.internal.** to avoid conflicts with other protobuf versions used in applications.
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);Install with Tessl CLI
npx tessl i tessl/maven-com-typesafe-akka--akka-protobuf-v3-2-13