How to ignore null objects when writing JSON using JsonCpp

According to the Google JSON Style Guide, it is recommended that you delete null or null values.

When using JsonCpp, how to remove null or null values, either from the structure of an object or when writing to a stream?

I need the following code:

#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; 

for creating:

 { "id": 4, } 
+5
source share
3 answers

You can add a preliminary process to remove empty elements, for example:

 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; } } } 

And finally:

 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; 
+4
source

Personally, I would prefer a recording option that allows you to filter out empty / null properties when recording. Thus, you can define your own class, for example, class MyFastWriter : public FastWriter , override printValue to process objectValue and call FastWriter::writeValue for the rest. Unfortunately, the JsonCpp API has defined the printValue member printValue as confidential, so you cannot override it (or even call it) from a custom derived class.

Therefore, I see only three main ways to achieve what you want: (1) Adaptation of the json value before writing, (2) defining your own writer class and copying a lot of code from FastWriter or (3) change the source code of FastWriter .

There is already a correct answer for option (1) provided by Jarod42.

Option (2) and (3) share the main flaw that you copy or modify implementation details that may change in future versions of JsonCpp; But still, if someone knows about the shortcomings that arise when changing or copying the source code of the library, this may be an option. The situation may be that the json value at hand should contain empty properties, it is very large and should be written quite often; it becomes inconvenient to copy the value, changing it for writing only and writing it again and again.

I'm certainly not a friend changing source code; In any case, see the following adapted version of FastWriter::writeValue , which allows you to get the desired result:

 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; } } 
+1
source

I assume that the values ​​you set are not constant values ​​and you are saving data from a class or some other data structure. In this case, you can simply check the data on the C ++ side and completely skip the json["varName"] .

Everything that you put in the JSON file will be in the final JSON, because you set this field in the JSON file to something. As you said, it is recommended not to include the NULL / empty values, but this is not necessary. NULL, empty, or default values ​​remain the values ​​that some people might want in their JSON file to show that a particular object does not have this record, but it is still a field in that data.

I would use an empty array as is for the name field in your JSON file, so the reader can say that “Oh, well, this object has no names”, and if it wasn “It was supposed to happen, or if it it will be strange, even non-technical clients will be able to pass you through it, and debugging will be much easier. If this is not part of the network code, and you need to have the fastest response time. Otherwise, just turn it on.

Golden debug rule: Thich files save lives.

0
source

Source: https://habr.com/ru/post/1264807/


All Articles