Java中Protobuf重复字段构建异常及跨语言请求失败求助
Proto3重复字段构建与跨语言交互格式问题
1. 定义的Proto文件
syntax = "proto3"; option java_multiple_files = true; option java_package = "com.anusoft"; message Request { repeated string subjects = 1; }
2. 直接使用setSubjects构建对象的错误
尝试用以下代码构建对象时:
Request request1 = Request.newBuilder() .setSubjects(0, "Maths") .setSubjects(1, "Science") .build();
抛出索引越界异常:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.ArrayList.rangeCheck(ArrayList.java:657) java.util.ArrayList.set(ArrayList.java:448) at com.google.protobuf.LazyStringArrayList.set(LazyStringArrayList.java:140) at com.google.protobuf.LazyStringArrayList.set(LazyStringArrayList.java:61) at com.anusoft.Request$Builder.setSubjects(Request.java:468) at com.anusoft.grpc.Main.main(Main.java:8)
原因:setSubjects方法仅用于修改已存在索引位置的元素,初始构建器的subjects列表为空,没有索引0的元素,因此触发越界错误。
3. 正确构建后的格式匹配问题
改用批量添加的方式构建对象:
Request request2 = Request.newBuilder() .addAllSubjects(Arrays.asList("Maths", "Science")) .build();
直接打印对象得到的是Protobuf原生文本格式:
subjects: "Maths" subjects: "Science"
但与.NET服务器交互时,期望的是JSON数组格式:
subjects: ["Maths", "Science"]
因格式不匹配导致服务器无法处理请求。
解决方案
解决
setSubjects的越界问题
不要直接使用setSubjects修改空列表的索引,改用添加类方法:- 逐个添加:
Request request = Request.newBuilder() .addSubjects("Maths") .addSubjects("Science") .build(); - 批量添加(即你已使用的
addAllSubjects方式)
- 逐个添加:
解决跨语言交互的格式问题
Protobuf的toString()方法输出的是其原生文本格式,而.NET服务器期望的是JSON格式。需要将Protobuf对象序列化为JSON:
引入Protobuf的JSON工具类,执行序列化:import com.google.protobuf.util.JsonFormat; // 构建对象 Request request = Request.newBuilder() .addAllSubjects(Arrays.asList("Maths", "Science")) .build(); // 序列化为JSON字符串 String jsonRequest = JsonFormat.printer().print(request); // 此时jsonRequest的内容为 {"subjects": ["Maths", "Science"]}将这个JSON字符串发送给.NET服务器,即可匹配预期格式。
内容的提问来源于stack exchange,提问作者anurag tripathi
相关产品推荐
相关产品推荐

