2017-02-27 2 views
5

Gemäß Google JSON style guide ist es ratsam, leere oder Nullwerte zu entfernen.Ignorieren von Null-Objekten beim Schreiben von JSON mit JsonCpp

Wie können bei der Verwendung von JsonCpp leere oder Nullwerte entfernt werden, entweder aus der Objektstruktur oder beim Schreiben in einen Stream?

Ich möchte den folgenden 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; 

zu produzieren:

{ 
    "id": 4, 
} 
+0

'sed '/: \ W * null \ W *,/d''? – YSC

Antwort

4

Sie eine Vorbestellung Prozess in den leeren Mitglieder zu entfernen, so etwas wie:

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

Und so endlich:

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

Persönlich würde ich eine Option im Writer bevorzugen, die es ermöglicht, leere/Null-Eigenschaften beim Schreiben herauszufiltern. Dabei könnte man eine eigene Klasse wie class MyFastWriter : public FastWriter definieren, printValue für die Behandlung des Typs objectValue entsprechend überschreiben und FastWriter::writeValue für den Rest anrufen. Unglücklicherweise hat die JsonCpp-API die Elementfunktion printValue als privat definiert, sodass Sie sie nicht von einer benutzerdefinierten abgeleiteten Klasse überschreiben (und nicht einmal aufrufen) können.

Daher sehe ich nur drei prinzipielle Möglichkeiten, um zu erreichen, was Sie wollen: (1) Anpassung der Json-Wert vor dem Schreiben, (2) Definieren einer eigenen Writer-Klasse und Kopieren von viel Code von FastWriter, oder (3) ändern der Quellcode von FastWriter.

Es gibt bereits eine richtige Antwort für die Option (1) von Jarod42.

Option (2) und (3) teilen den Hauptnachteil, dass Sie Implementierungsdetails kopieren oder ändern, die sich in zukünftigen Versionen von JsonCpp ändern könnten; Aber wenn man sich der Nachteile bewusst ist, die mit dem Ändern oder Kopieren des Quellcodes einer Bibliothek einhergehen, ist dies eine Option. Eine Situation könnte sein, dass der vorliegende json-Wert leere Eigenschaften behält, sehr groß ist und ziemlich oft geschrieben werden muss; dann wird es unhandlich, den Wert zu kopieren, ihn nur zum Schreiben zu ändern und ihn dann immer wieder zu schreiben.

Ich bin sicher kein Freund des Änderns von Quellcode; Wie auch immer, finden Sie in der folgenden angepasste Version von FastWriter::writeValue, die den Ausgang erreicht Sie wollen:

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

Beachten Sie, dass je nach der gewünschten Definition von * empty * der rekursive Fall komplizierter wäre: {"a": "a", "empty_rec": {"empty": null}} '. – Jarod42

0

Ich gehe davon aus, dass die Werte Sie Einstellung sind keine konstanten Werte und Sie sind zum Speichern von Daten von einer Klasse oder eines anderen Datenstruktur. In diesem Fall können Sie einfach die Daten in C++ Seite überprüfen und json["varName"] Teil vollständig überspringen.

Was immer Sie in eine JSON-Datei schreiben, wird im endgültigen JSON sein, weil Sie dieses Feld in der JSON-Datei auf etwas setzen. Wie Sie gesagt haben, ist es ratsam, NULL/leere Werte nicht zu enthalten, aber es ist kein Muss. NULL, leer oder Standardwerte sind immer noch Werte, die manche Leute in ihrer JSON-Datei haben wollen, um spezifisch anzuzeigen, dass diese bestimmte Entität diesen Eintrag nicht hat, aber immer noch ein Feld in diesen Daten ist.

Ich würde das leere Array wie für das name Feld in Ihrer JSON-Datei verwenden, auf diese Weise kann der Leser sagen, "Oh ok, dieses Objekt hat keine Namen Werte zu ihm" und wenn das wasn ' Es sollte passieren, oder wenn es sich komisch anfühlt, könnten auch nicht-technische Kunden Sie durch das System führen und das Debugging wäre viel einfacher. Es sei denn, dies ist Teil eines Netzwerkcodes und Sie müssen die schnellsten Antwortzeiten haben. Ansonsten, schließen Sie es einfach ein.

Goldene Regel des Debuggens: Thich-Dateien retten Leben.

Verwandte Themen