根据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,
}
答案 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文件拯救生命。