2014-01-09 10 views
6

Problemzusammenfassung: Ich versuche, einen Hash zu JSON unter Verwendung der Oj gem zu serialisieren. Es scheint, dass Oj die Symbolschlüssel des Hash nicht automatisch in Strings konvertiert. Ich frage mich, ob Oj eine Option hat, während der Serialisierung zu "stringifizieren"? Konvertieren von Symbolen in Zeichenfolge beim Serialisieren mit Oj.dump

Dies ist ein Beispiel für meine hash:

example_hash = 
{:id=>1234, 
    :asset_number=>"1234-5678", 
    :latitude=>34.78495, 
    :longitude=>-92.12899, 
    :last_tracking_record_id=>123456789, 
    :bearing=>42, 
    :threat_level=>:severe} 

und die oben wie so gemacht:

render json: Oj.dump(example_hash) 

Die resultierende JSON leiden Schlüssel hat, die genauso aussehen wie die oben, was bedeutete, würde ich müssen auf Elemente in JavaScript wie folgt zugreifen: response[:asset_number]. Da der clientseitige Code vor Monaten implementiert wurde und erst jetzt Oj hinzugefügt wurde, würde ich es vorziehen, eine Möglichkeit zu finden, die Schlüssel serialisierend serverseitig zu stringifizieren.

Oj hat eine Option namens symbol_keys, die ein boolescher Wert ist, aber es hat keine Auswirkung in dieser Hinsicht, wenn es auf true oder gesetzt wird.

Die einzige Lösung, die ich bis jetzt gefunden habe, ist die Verwendung with_indifferent_access wie in this answer vorgeschlagen, aber in einigen Fällen habe ich Arrays von Hashes; Während ich diese Methode technisch für jeden Hash in diesem Array aufrufen kann, würde Oj, da es die Json-Serialisierung beschleunigen soll, lieber einen Weg finden, dies mit Oj selbst zu tun. Letztendlich frage ich mich, ob es eine Option oder Einstellung in Oj gibt, die diese während Serialisierung durchführen wird.

Antwort

9

Während ich die Frage schrieb, konnte ich die Antwort finden. Da ich in Bezug auf dieses Problem keine weiteren Antworten zu StackOverflow finden kann (speziell in Bezug auf das Oj-Juwel), werde ich diesen Beitrag in der Hoffnung behalten, dass er anderen in meiner Situation helfen wird.

Gemäß this previously discussed issue on GitHub wird die Einstellung mode auf :compat tatsächlich die Symbole in Strings konvertieren. Also meine Render Linie sieht nun wie folgt aus:

render json: Oj.dump(example_hash, mode: :compat) 

Nach dem Oj documentation for default_options, :compat Modus ist wie folgt definiert:

... mit anderen Systemen kompatibel. Es wird jedes Objekt serialisieren, aber prüfen, ob das Objekt eine to_hash() - oder to_json() -Methode implementiert. Wenn diese Methode existiert, wird sie zum Serialisieren des Objekts verwendet. Die to_hash() ist flexibler und erzeugt eine konsistentere Ausgabe, so dass sie eine Präferenz gegenüber der to_json() -Methode hat. Wenn weder die Methoden to_json() noch to_hash() existieren, wird die interne Oj-Objektvariable verwendet.

Also, wenn ich das richtig bin zu interpretieren, wie es scheint diese Lösung funktioniert, weil es letztlich die to_json Methode der Hash-Klasse ist.

Ich bin unsicher, ob ich die Leistung (entweder positiv oder negativ) beeinflusst habe, aber es erspart mir zumindest davor, with_indifferent_access oder to_json im Falle eines Arrays manuell aufzurufen.

aktualisieren

In Bezug auf Leistung, tat cmwright einige Benchmarking und kam mit diesen Ergebnissen auf:

Rehearsal ---------------------------------------------- 
json  13.990000 0.250000 14.240000 (14.257051) 
oj default 3.260000 0.230000 3.490000 ( 3.491028) 
oj compat 3.360000 0.240000 3.600000 ( 3.593109) 
------------------------------------ total: 21.330000sec 

       user  system  total  real 
json  13.740000 0.240000 13.980000 (13.992641) 
oj default 3.020000 0.230000 3.250000 ( 3.248077) 
oj compat 3.060000 0.230000 3.290000 ( 3.286443) 

wie die compat Option scheint zumindest auf einer Stufe mit den Optionen Standard ist Oj und wesentlich effizienter als plain 'ol to_json.

Dies ist die gist den Benchmark-Code enthält.

+1

Ich habe gerade ein Benchmarking durchgeführt, um sicherzustellen, dass der compat-Modus die Leistung nicht beeinträchtigt, und war angenehm überrascht von meinem Anwendungsfall. Ich benutzte einen Hash (string => int) mit 10.000 Schlüssel und bekam folgende Ergebnisse mit Benchmark.bmbm (kann nicht in diesen Kommentaren zu formatieren scheinen): json 14,550000 0,270000 14,820000 (14,855023) oj Standard 3,420000 0,250000 3,670000 (3,684655) oj compat 3.500000 0.260000 3.760000 (3.758900) – cmwright

+0

@cmwright Ah sehr nett. Nach einiger Zeit war ich mir ziemlich sicher, dass es keine Performance-Probleme gab, aber ich habe nie wirklich Benchmarks gemacht. Das ist großartig zu wissen. Diese Frage scheint mehr Ansichten zu bekommen, als ich erwartet hatte, also würde es Ihnen etwas ausmachen, wenn ich Ihre Daten der Antwort hinzufügen würde (natürlich mit korrektem Kredit)? –

+1

Ja, unbedingt. Ich kann einen Kern des Codes posten, den ich das nächste Mal benutzte, das ich an einem Computer – cmwright

Verwandte Themen