【问题标题】:Thrift Required Field C++Thrift 必填字段 C++
【发布时间】:2014-01-23 08:14:31
【问题描述】:
Thrift File:
struct Sub {
1: required i32 number
}

struct Message {
1: required Sub sub
}

Message m;
m.write(protocol.get());
Message parsedM;
parsedM.read(protocol2.get());
std::cout << parsedM.sub.number;

SourceCode

Thrift 不应该引发错误,或者是否有任何其他可能正确检查是否已设置所有必填字段? 否则我看不出该关键字有什么实际意义。

【问题讨论】:

    标签: c++ protocols thrift


    【解决方案1】:

    简答

    是的,如果反序列化时数据不存在,您应该得到TProtocolException::INVALID_DATA。在您的示例中情况并非如此,因此您不会遇到异常。

    长答案

    这是基于您的 IDL 生成的 C++ read() 方法之一。注意isset_number 及其使用方式:

    uint32_t Sub::read(::apache::thrift::protocol::TProtocol* iprot) {
    
      uint32_t xfer = 0;
      std::string fname;
      ::apache::thrift::protocol::TType ftype;
      int16_t fid;
    
      xfer += iprot->readStructBegin(fname);
    
      using ::apache::thrift::protocol::TProtocolException;
    
      bool isset_number = false;
    
      while (true)
      {
        xfer += iprot->readFieldBegin(fname, ftype, fid);
        if (ftype == ::apache::thrift::protocol::T_STOP) {
          break;
        }
        switch (fid)
        {
          case 1:
            if (ftype == ::apache::thrift::protocol::T_I32) {
              xfer += iprot->readI32(this->number);
              isset_number = true;
            } else {
              xfer += iprot->skip(ftype);
            }
            break;
          default:
            xfer += iprot->skip(ftype);
            break;
        }
        xfer += iprot->readFieldEnd();
      }
    
      xfer += iprot->readStructEnd();
    
      if (!isset_number)
        throw TProtocolException(TProtocolException::INVALID_DATA);
      return xfer;
    }
    

    那么为什么它在您的示例中有效?

    正如我们所见,required 字段预计会出现在反序列化数据中,而 optional(和默认)字段可能会丢失。但是标记为required 的字段(和默认字段)也总是写入到传输中,optional 仅在分配了值时。因此,您读取了之前序列化的数据:

    uint32_t Sub::write(::apache::thrift::protocol::TProtocol* oprot) const {
      uint32_t xfer = 0;
      xfer += oprot->writeStructBegin("Sub");
    
      xfer += oprot->writeFieldBegin("number", ::apache::thrift::protocol::T_I32, 1);
      xfer += oprot->writeI32(this->number);
      xfer += oprot->writeFieldEnd();
    
      xfer += oprot->writeFieldStop();
      xfer += oprot->writeStructEnd();
      return xfer;
    }
    

    请注意,Thrift 并不关心该字段是否包含 有效 数据。这都是关于序列化方面的。

    推荐阅读

    Diwaker Gupta's "Missing Guide" 很好地解释了required 的优缺点。

    【讨论】:

    • 可惜 Thrift 中没有验证机制,但可能是设计问题。
    • @MichaelLatz - 我使用 thrift 已经 3 年了,从未注意到这方面的问题。但是如果你需要它——实现它并提交一个补丁,只要它不破坏当前的功能(即可选)我认为不会有异议。
    • 也许,是的。如thrift.apache.org/about 中所述,主要目的之一是保持轻量级 - 这意味着一些设计决策是针对该目标做出的。一个特定的设计决定是否是一个“问题”,有点主观,可以讨论。 Thrift 并不是众所周知的万事通 + 万事通。 OTOH,我们仍在添加功能。底线:提交补丁是开始讨论的好主意。
    猜你喜欢
    • 1970-01-01
    • 2014-08-06
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    相关资源
    最近更新 更多