2016-04-21 6 views
0

Ich benutze RapidJSON, um große GeoJSON-Dateien zu analysieren. Der größte Teil des Inhalts in diesen Dateien (und damit der Speicher nach dem Parsen) sind riesige Koordinatenfelder. Für meine Bewerbung interessiert mich das nicht. Ich würde es vorziehen, sie zu überspringen (nicht Speicher für sie zu reservieren) beim Parsen. Basierend auf einigen Tests mit der SAX API, erwarte ich, dass dies die Geschwindigkeit des Parsings ungefähr verdoppelt.Überspringe bestimmte Felder beim Parsen eines Dokuments mit RapidJSON

Mein erster Gedanke war, eine benutzerdefinierte Handler zu schreiben. Ich müsste mein eigenes Value-Objekt erstellen, indem ich meinen eigenen Stack verwende, aber was die Klasse GenericDocument erledigt.

Mein nächster Gedanke war die Unterklasse GenericDocument. Seine ParseStream und Handler-Methoden sind jedoch nicht virtual, so dass ich es nicht nutzen kann, meine eigenen zu verwenden. Ich könnte meine eigene ParseStream implementieren, aber das stack_ Feld ist privat, so dass sogar eine Unterklasse nicht darauf zugreifen kann.

Ist ein benutzerdefinierter Handler mit seinem eigenen Stack der richtige Weg, um hier zu gehen? Hat jemand so etwas schon einmal gemacht?

+0

FWIW, hier ist eine [Version] (https://gist.github.com/danvk/90beec9f0387788eca9c1ba8402dbee1), die 'GenericValue' mit einer eigenen Stack- und Handler-Implementierung abbildet. Es funktioniert und ist schnell, lässt aber hinsichtlich der Code-Duplikation viel zu wünschen übrig. Ich würde gerne ein Feedback darüber bekommen, ob es einen besseren Ansatz gibt. – danvk

Antwort

1

Während der Implementierung der JSON-Schema-Validator-Funktion in RapidJSON, habe ich eine neue API für Document::Populate(generator) hinzugefügt, die einen Generator verwendet, um den Inhalt des Dokuments zu füllen. Es sollte dafür geeignet sein.

// Parse JSON from reader, validate the SAX events, and store in d. 
Document d; 
SchemaValidatingReader<kParseDefaultFlags, FileReadStream, UTF8<> > reader(is, schema); 
d.Populate(reader); 

d.Populate(generator) rufen generator(d) und dann generator erzeugt SAX Ereignisse und senden zu d:

wurde in here Zeit gezeigt.

Daher sollte es möglich sein, einen benutzerdefinierten SAX-Handler zu schreiben, der einige SAX-Ereignisse filtert und die Ereignisse an das Dokument weiterleitet.

Ein Beispiel mag noch besser sein. Sie können ein Problem fallen lassen.


Aktualisierung: Zwei Beispiele wurden hinzugefügt.

  • filterkey: Ein Befehlszeilenprogramm zum Entfernen aller Werte mit benutzerdefiniertem Schlüssel.
  • : Gleiches Werkzeug wie oben, aber es zeigt, wie man einen Generator verwendet, um einen Document zu füllen.
  • +0

    Danke für den Vorschlag. Ich habe [eine Ausgabe] eingereicht (https://github.com/miloyip/rapidjson/issues/613). – danvk

    Verwandte Themen