使用JsonCpp编写JSON时如何忽略空对象

时间:2017-02-27 22:24:09

标签: c++ json jsoncpp

根据Google JSON style guide,建议删除空值或空值。

使用JsonCpp时,如何从对象结构或写入流中删除空值或空值?

我想要以下代码:

#include <json/json.h>
#include <json/writer.h>

Json::Value json;
json["id"] = 4;
// The "name" property is an empty array.
json["name"] = Json::Value(Json::arrayValue);
Json::FastWriter fw;
std::cout << fw.write(json) << std::endl;

生产:

{
    "id": 4,
}

3 个答案:

答案 0 :(得分:4)

您可以添加预处理以删除空成员,例如:

void RemoveNullMember(Json::Value& node)
{
    switch (node.type())
    {
        case Json::ValueType::nullValue: return;
        case Json::ValueType::intValue: return;
        case Json::ValueType::uintValue: return;
        case Json::ValueType::realValue: return;
        case Json::ValueType::stringValue: return;
        case Json::ValueType::booleanValue: return;
        case Json::ValueType::arrayValue:
        {
            for (auto &child : node)
            {
                RemoveNullMember(child);
            }
            return;
        }
        case Json::ValueType::objectValue:
        {
            for (const auto& key : node.getMemberNames())
            {
                auto& child = node[key]
                if (child.empty()) // Possibly restrict to any of
                                   // nullValue, arrayValue, objectValue
                {
                    node.removeMember(key);
                }
                else
                {
                    RemoveNullMember(node[key]);
                }
            }
            return;
        }
    }
}

最后:

Json::Value json;
json["id"] = 4;
json["name"] = Json::Value(Json::arrayValue); // The "name" property is an empty array.
RemoveNullMember(json); // Or make a copy before.
Json::FastWriter fw;
std::cout << fw.write(json) << std::endl;

答案 1 :(得分:1)

我个人更喜欢编写器中的一个选项,它允许在写入时过滤掉空/ null属性。因此,可以定义自己的类class MyFastWriter : public FastWriter,覆盖printValue以相应地处理类型objectValue,并为其余类别调用FastWriter::writeValue。不幸的是,JsonCpp API已将成员函数printValue定义为私有,因此您无法从自定义派生类中覆盖它(甚至不能调用它)。

因此,我只看到了实现你想要的三种主要方法:(1)在写入之前调整json值,(2)定义自己的编写器类并从FastWriter复制大量代码,或者( 3)更改FastWriter

的源代码

Jarod42提供的选项(1)已经有了正确的答案。

选项(2)和(3)共享您复制或更改可能在JsonCpp的未来版本中更改的实现细节的主要缺点;但是,如果人们非常清楚改变或复制库的源代码所带来的缺点,那么它可能是一种选择。一种情况可能是手头的json值应保持空的属性,非常大,并且必须经常写入;那么复制价值,改变它只是为了写作,然后一次又一次地写它是不容易的。

我肯定不是改变源代码的朋友;无论如何,请参阅FastWriter::writeValue的以下改编版本,它可以实现您想要的输出:

void FastWriter::writeValue(const Value& value) {
  switch (value.type()) {

  // cases handling the other value.types remain as is...
  ...

  // case handling objectValue is adapted:
  case objectValue: {
    Value::Members members(value.getMemberNames());
    document_ += '{';

    // inserted flag indicating that the first element is to be written:
    bool isFirst = true;

    for (Value::Members::iterator it = members.begin(); it != members.end();
         ++it) {

      const std::string& name = *it;

      // inserted to skip empty/null property values
      if(value[name].empty() || value[name].isNull())
          continue;

//    Replaced: necessary because the first written entry is not necessarily members.begin:
//      if (it != members.begin())
//        document_ += ',';
      if (!isFirst)
          document_ += ',';
      else
          isFirst = false;

      // Kept as is...            
      document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
      document_ += yamlCompatiblityEnabled_ ? ": " : ":";
      writeValue(value[name]);
    }
    document_ += '}';
  } break;
  }
}

答案 2 :(得分:0)

我假设您设置的值不是常量值,而是从类或其他数据结构中保存数据。在这种情况下,您只需检查C ++端的数据并完全跳过json["varName"]部分。

无论你放在JSON文件中的是什么,都会出现在最终的JSON中,因为你正在将JSON文件中的那个字段设置为某个东西。如你所说,建议不包括NULL /空值,但它不是必须的。 NULL,空值或默认值仍然是某些人在其JSON文件中可能想要的值,专门用于显示特定实体没有该条目,但它仍然是该数据中的字段。

我会在JSON文件中使用空数组作为name字段,这样读者可以说“哦,好吧,这个对象没有任何名称值”,如果这不应该发生,或者如果感觉很奇怪,即使是非技术客户也能指导您完成调试并且调试会更简单。除非这是网络代码的一部分,否则您需要具有最快的响应时间。否则,只需加入它。

调试的黄金法则:Thich文件拯救生命。