proto3 gRPC中Any转JSON报Cannot find type for url异常排查
proto3 gRPC消息转JSON报
Cannot find type for url问题修复 问题核心原因
两个问题共同导致异常:
- 客户端构造
google.protobuf.Any字段的方式不符合规范 - 服务端Json序列化时的类型注册表未正确注册所有用到的消息类型
toJava2方法存在的明确错误
- 仅注册了
InsertRequest的描述符,未注册tagProperties这个Any字段里实际存储的所有消息类型的描述符,JsonFormat解析Any时找不到类型映射 - 构造Any的客户端逻辑错误:手动调用
setValue()塞原始字节,未设置type_url字段,JsonFormat序列化Any时必须依赖type_url匹配类型,无该值必然抛出找不到类型URL的异常 - 方法逻辑不完整:构造完Printer后未执行后续的JSON转Java对象逻辑,直接返回null
修复步骤
1. 修正客户端构造Any的逻辑
google.protobuf.Any不能直接存储裸字节,必须通过pack()方法打包具体的Protobuf消息实例,自动填充合法的type_url。基础类型值需要使用Protobuf内置的包装类型承载,不能直接塞字符串、数字的原始字节。
正确的请求构造代码:
import com.google.protobuf.StringValue; import com.google.protobuf.Any; // 字符串值用StringValue包装 StringValue userNameVal = StringValue.of("zzz"); // pack方法自动填充type_url,打包为Any类型 Any userNameAny = Any.pack(userNameVal); InsertRequest request = InsertRequest.newBuilder() .setTagName("facebook") .putTagProperties("userName", userNameAny) .build();
2. 修正服务端序列化逻辑
TypeRegistry需要注册所有可能存入Any字段的消息类型的描述符,包括Protobuf内置的基础类型包装类、你自定义的业务消息类,不能只注册外层的InsertRequest。
修正后的转换方法代码:
public static <T> T toJava(Message sourceMessage, Class<T> clazz) { if (sourceMessage == null) { return null; } try { JsonFormat.TypeRegistry typeRegistry = JsonFormat.TypeRegistry.newBuilder() // 注册自定义业务消息类型 .add(InsertRequest.getDescriptor()) // 注册protobuf内置基础类型包装类,根据你实际存的类型增减 .add(StringValue.getDescriptor()) .add(Int32Value.getDescriptor()) .add(Int64Value.getDescriptor()) .add(BoolValue.getDescriptor()) .add(DoubleValue.getDescriptor()) .add(FloatValue.getDescriptor()) // 如果Any里存你自定义的其他proto消息,比如A类对应的proto消息,也要在这里add对应descriptor .build(); String jsonStr = JsonFormat.printer() .includingDefaultValueFields() .usingTypeRegistry(typeRegistry) .print(sourceMessage); return JSON.parseObject(jsonStr, clazz); } catch (InvalidProtocolBufferException e) { log.error("Proto消息转JSON异常", e); throw new BusinessException(CommonEnum.DATA_CONVERSION_EXCEPTION); } }
注意:如果要在Any中存储自定义实体,必须先定义对应的proto message生成Java类,不能直接传普通Java POJO,打包时同样使用
Any.pack(自定义消息实例)的方式,同时把该自定义消息的descriptor注册到TypeRegistry中。
内容的提问来源于stack exchange,提问作者swayingleaves
相关产品推荐
相关产品推荐

