【问题标题】:Thrift - converting from simple JSONThrift - 从简单的 JSON 转换
【发布时间】:2013-12-14 05:15:55
【问题描述】:

我创建了以下 Thrift 对象:

struct Student{
        1: string id;
        2: string firstName;
        3: string lastName
}

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

于是我写了如下代码:

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 解析为地图和列表,然后转储并理解它。然后弄清楚如何提取你想要的数据。
  • 我很抱歉,但我不明白你的意思。我应该解析什么json。我有非常简单的节俭结构,不需要地图和列表。
  • 问题是您使用的工具比您需要(和理解)更复杂。从简单开始。

标签: java json thrift thrift-protocol


【解决方案1】:

您错过了 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,我们也需要知道数据的语义才能真正利用该文件中的内容:它是 customer data record 吗?还是SOAP envelope?也许是configuration file

这就是 DTD 或 XML Schema 发挥作用的地方,它们的存在是为了描述 XML 数据的内容。如果不知道逻辑结构,您就会迷失方向,因为有无数种可能的方式可以用 XML 表达事物。 JSON 也是如此,只是 JSON schema descriptions 不太常用。

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

不,因为 Thrift 背后的目的和想法是有一个框架来反序列化事物和/或尽可能高效地实现 RPC 服务器和客户端。它不打算有一个通用的文件解析器。相反,Thrift 只读取和说出它自己的一组格式,即plugged into the architecture as protocols:Thrift Binary、Thrift JSON、Thrift Compact 等等。

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

【讨论】:

  • 看起来 twitter 正在使用相同的方法序列化 json:github.com/twitter/commons/blob/master/src/java/com/twitter/… 唯一的区别是他们使用的是 thrift 0.5.0 而我使用的是 0.9.0。我将尝试生成二进制文件并在此版本上运行我的代码。我感觉自 0.5 版本以来行为发生了变化。
  • @danny.lesnik:你读过上面的评论了吗?它说“可以编码和解码节俭结构的编解码器” - 它没有说“可以编码和解码任何 JSON 结构的编解码器”。
猜你喜欢
  • 2017-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-02
  • 2011-10-08
  • 2020-05-31
  • 1970-01-01
相关资源
最近更新 更多