概念定义
Protocol Buffers(protobuf)是模式先行的序列化系统:消息在 .proto 文件中用带编号的字段定义,编译器为其生成多种语言的代码。在线路上它是紧凑的二进制格式,以字段编号而非名称索引,因此负载小、解析快。带来兼容性的是字段编号而非名称:未知字段会被保留,新的可选字段可在不破坏旧读取方的前提下添加。
为什么重要
JSON 可读但在规模下冗长且解析慢,且不携带模式。Protobuf 提供更小的消息、更快的解析,以及能在编译期发现错误的生成类型。其字段编号方案从设计上提供兼容性:生产者可以添加旧消费者会忽略的字段,且随着模式增长,旧数据仍可读取。这使它很适合持续演进的高吞吐服务与流式接口。
工程实践
把字段编号视为永久:绝不复用已退役的编号,代之以保留编号而非删除,因为复用的标签会把旧数据重新解释为新类型。字段默认设为可选,用添加而非删除,并以向后兼容的步骤演进模式。把 protobuf 与模式注册表或带版本的契约配合,使每条被存储或流式传输的消息仍可解码;并记住解释字节需要模式——把它与数据一同保存。
代码示例
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import java.util.List;
import java.util.Map;
public class ObjectSerialization {
@JsonIgnoreProperties(ignoreUnknown = true)
static class Configuration {
@JsonProperty("app_name")
private String appName;
@JsonProperty("max_connections")
private int maxConnections;
@JsonProperty("features")
private List<String> features;
@JsonCreator
public Configuration(
@JsonProperty("app_name") String appName,
@JsonProperty("max_connections") int maxConnections,
@JsonProperty("features") List<String> features
) {
this.appName = appName;
this.maxConnections = maxConnections;
this.features = features;
}
@Override
public String toString() {
return appName + " (max=" + maxConnections + ", features=" + features + ")";
}
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
String json = """
{
"app_name": "MyApp",
"max_connections": 100,
"features": ["auth", "logging", "cache"]
}
""";
Configuration config = mapper.readValue(json, Configuration.class);
System.out.println("Deserialized: " + config);
String output = mapper.writeValueAsString(config);
System.out.println("Serialized: " + output);
}
}