protobuf和json互转时应该注意的问题

  • 2017-11-29
  • 浏览 (3248)

网上protobuf的资料不是很多,遇到问题比较费时间。说说可能会遇到的两个问题。

官方的说明:

https://developers.google.com/protocol-buffers/docs/proto3#json

JSON Mapping

Proto3 supports a canonical encoding in JSON, making it easier to share data between systems. The encoding is described on a type-by-type basis in the table below.

If a value is missing in the JSON-encoded data or if its value is null, it will be interpreted as the appropriate default value when parsed into a protocol buffer. If a field has the default value in the protocol buffer, it will be omitted in the JSON-encoded data by default to save space. An implementation may provide options to emit fields with default values in the JSON-encoded output.


1、protobuf buffer转换成json时候会把字段值是默认值的数据忽略,但它提供了方法可以解决这个问题。

首先添加依赖:

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java-util</artifactId>
    <version>3.5.0</version>
</dependency>
代码使用:
SomeProto.Builder builder = SomeProto.newBuilder();
SomeProto message = builder.build();
String json = com.google.protobuf.util.JsonFormat.printer().includingDefaultValueFields().print(message);

上面这段代码虽然没有给message设值,但因为使用了includingDefaultValueFields方法,所以会把所有的字段都输出。但如果没有使用includingDefaultValueFields方法就会只输出 {} 。


2、在json字符串转换成protobu的Message对象时,如果存在Message对象不存在的字段时会报InvalidProtocolBufferException,此时需要使用ignoringUnknownFields

SomeProto.Builder builder = SomeProto.newBuilder();
Stirng json = some json data...
JsonFormat.parser().ignoringUnknownFields().merge(json, builder);
SomeProto proto = builder.build();


最后贡献将实体类转换成json再转成proto对象工具类:

import com.alibaba.fastjson.JSON;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.TextFormat.ParseException;
import com.google.protobuf.util.JsonFormat;

public class ProtobufUtils {

	/**
	 * json数据转换为pb对象
	 */
	@SuppressWarnings("unchecked")
	public static <T> T json2pb(String json, Message.Builder builder) throws ParseException, InvalidProtocolBufferException {
		if (builder == null) {
			return null;
		}
		JsonFormat.parser().ignoringUnknownFields().merge(json, builder);
		return (T) builder.build();
	}
	
	/**
	 * json数据转换为pb对象
	 */
	public static <T> T json2pb(Object entity, Message.Builder builder) throws ParseException, InvalidProtocolBufferException {
		if (builder == null || entity == null) {
			return null;
		}
		return json2pb(JSON.toJSONString(entity), builder);
	}
	
}

参考资料:https://github.com/HubSpot/jackson-datatype-protobuf/issues/12
1  赞