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)

我错过了什么吗?

4

1 回答 1

7

您错过了一个事实,即 Thrift 的 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 Binary、Thrift JSON、Thrift Compact 等等。

您可以做什么:除了我在回答的第一部分中所说的之外,您可以考虑编写自己的自定义 Thrift 协议实现以支持您选择的特定 JSON 格式。这并不难,值得一试。

于 2013-11-28T18:36:04.377 回答