将JSON字符串转为Thrift对象时遇TProtocolException错误求助
问题描述
我有一个JSON字符串,想要将其转换为Thrift对象。Thrift定义如下:
struct Person { 1: optional string name; }
我的C++代码如下:
#include <thrift/TBase.h> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/protocol/TJSONProtocol.h> #include <thrift/transport/TBufferTransports.h> #include <thrift/transport/TTransportUtils.h> #include <cstring> #include "Person_types.h" int main() { std::string s = R"({"name": "alice"})"; auto transport = std::make_shared<apache::thrift::transport::TMemoryBuffer>((uint8_t *)s.data(), s.length()); auto protocol_factory = std::make_shared<apache::thrift::protocol::TJSONProtocolFactory>(); auto protocol = protocol_factory->getProtocol(transport); Person obj; obj.read(protocol.get()); }
运行时遇到错误,错误信息如下:
terminate called after throwing an instance of 'apache::thrift::protocol::TProtocolException' what(): Expected '"'; got 'n'. Aborted (core dumped)
使用的Thrift版本为0.12.0,请求解决该问题。
解决方案
Thrift的TJSONProtocol不支持标准JSON解析,它采用Thrift自定义的JSON格式,要求根对象的键必须是Thrift字段的整数ID,而非字段名。你传入的标准JSON用了字段名name,不符合协议要求,因此报错。
提供两种解决方法:
方法一:改用Thrift自定义JSON格式
将输入JSON改为以字段ID作为键的格式:
std::string s = R"({"1": "alice"})";
修改后即可正常解析。
方法二:使用TSimpleJSONProtocol(推荐)
Thrift 0.11.0及以上版本提供了TSimpleJSONProtocol,支持解析标准JSON(用字段名而非ID)。修改步骤如下:
- 添加头文件引入:
#include <thrift/protocol/TSimpleJSONProtocol.h>
- 替换协议工厂:
// 替换原有的TJSONProtocolFactory auto protocol_factory = std::make_shared<apache::thrift::protocol::TSimpleJSONProtocolFactory>();
修改后的完整代码:
#include <thrift/TBase.h> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/protocol/TJSONProtocol.h> #include <thrift/protocol/TSimpleJSONProtocol.h> #include <thrift/transport/TBufferTransports.h> #include <thrift/transport/TTransportUtils.h> #include <cstring> #include "Person_types.h" int main() { std::string s = R"({"name": "alice"})"; auto transport = std::make_shared<apache::thrift::transport::TMemoryBuffer>((uint8_t *)s.data(), s.length()); auto protocol_factory = std::make_shared<apache::thrift::protocol::TSimpleJSONProtocolFactory>(); auto protocol = protocol_factory->getProtocol(transport); Person obj; obj.read(protocol.get()); }
此方法无需修改输入JSON格式,直接兼容标准JSON,更符合需求。
内容的提问来源于stack exchange,提问作者Hu Zhang
相关产品推荐
相关产品推荐

