Thrift - 从简单的JSON转换

7
我创建了以下的Thrift对象:
struct Student{
        1: string id;
        2: string firstName;
        3: string lastName
}

现在我想从JSON中读取这个对象。根据这篇文章,这是可能的。

所以我写了以下代码:

String json = "{\"id\":\"aaa\",\"firstName\":\"Danny\",\"lastName\":\"Lesnik\"}";
    StudentThriftObject s = new StudentThriftObject();
    byte[] jsonAsByte = json.getBytes("UTF-8");
    TMemoryBuffer memBuffer = new TMemoryBuffer(jsonAsByte.length);
    memBuffer.write(jsonAsByte);

    TProtocol proto = new TJSONProtocol(memBuffer);
    s.read(proto);

我得到的是以下异常:
Exception in thread "main" org.apache.thrift.protocol.TProtocolException: Unexpected character:i
    at org.apache.thrift.protocol.TJSONProtocol.readJSONSyntaxChar(TJSONProtocol.java:322)
    at org.apache.thrift.protocol.TJSONProtocol.readJSONInteger(TJSONProtocol.java:698)
    at org.apache.thrift.protocol.TJSONProtocol.readFieldBegin(TJSONProtocol.java:837)
    at com.vanilla.thrift.example.entities.StudentThriftObject$StudentThriftObjectStandardScheme.read(StudentThriftObject.java:486)
    at com.vanilla.thrift.example.entities.StudentThriftObject$StudentThriftObjectStandardScheme.read(StudentThriftObject.java:479)
    at com.vanilla.thrift.example.entities.StudentThriftObject.read(StudentThriftObject.java:413)
    at com.vanilla.thrift.controller.Main.main(Main.java:24)

我有什么遗漏吗?


首先将您的JSON解析为Map和List,然后将其转储并理解它。然后找出如何提取您想要的数据。 - Hot Licks
抱歉,我没有理解您的意思。我应该解析哪个JSON?我的Thrift结构非常简单,不需要使用Maps和Lists。 - danny.lesnik
1
问题在于你正在使用比你需要的(和理解的)更复杂的工具。从简单开始。 - Hot Licks
1个回答

7
您忽略了一个事实,即Thrift的JSON与您的JSON不同。字段名称未写入,而是写入(并期望)分配的字段ID编号。以下是Thrift的JSON协议示例:
[1,"MyService",2,1,{"1":{"rec":{"1":{"str":"Error: Process() failed"}}}}]

换句话说,Thrift不适用于解析任何类型的JSON。它支持一种特定的JSON格式作为可能的传输之一。
然而,根据您的JSON数据来源是什么,如果您能在两个方面使用它,Thrift可能仍然可以帮助您。在这种情况下,编写一个IDL来描述数据结构,将其提供给Thrift编译器,并将生成的代码和库的必要部分集成到您的项目中。
如果JSON的来源超出了您的范围,或者由于某些原因无法更改JSON格式,则需要找到另一种方法。
格式和语义是不同的东西。
在某种程度上,整个问题可以与XML进行比较:有一个通用的XML语法,告诉我们如何格式化事物,以便任何标准符合的XML处理器都可以读取它们。

了解XML的规则只是问题的一半,如果我们从某人那里得到一个特定的XML文件。即使我们的XML解析器可以成功读取该文件,因为它是格式良好的XML,我们需要知道数据的语义才能真正利用该文件中的内容:它是客户数据记录吗? 还是SOAP信封? 也许是配置文件

这就是DTD或XML Schema发挥作用的地方,它们存在于描述XML数据的内容。 如果不知道逻辑结构,你会感到迷失,因为在XML中表达事物有无数种可能的方式。 JSON也是完全相同的情况,除了JSON模式描述不太常用。

"所以,你的意思是,我们只需要一种告诉Thrift JSON如何组织的方法?"

不可以,因为Thrift的目的和想法是尽可能高效地拥有一个框架来序列化/反序列化事物和/或实现RPC服务器和客户端。它并不旨在拥有一个通用的文件解析器。相反,Thrift仅读取和使用其自己的一组格式,这些格式作为协议插入到体系结构中:Thrift二进制、Thrift JSON、Thrift紧凑等等。 您可以这样做:除了我在答案第一部分中提到的内容外,您可以考虑编写自己的自定义Thrift协议实现,以支持您选择的特定JSON格式。这并不难,值得一试。

看起来 Twitter 正在使用相同的方法序列化 JSON:https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/io/ThriftCodec.java,唯一的区别是他们正在使用 Thrift 0.5.0,而我正在使用 0.9.0。我将尝试生成二进制文件并在此版本上运行我的代码。我有一种感觉,自从 0.5 发布以来,行为已经发生了改变。 - danny.lesnik
@danny.lesnik:你看到顶部的评论了吗?它说“一个可以编码和解码Thrift结构的编解码器”,而不是“一个可以编码和解码任何JSON结构的编解码器”。 - JensG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接