2010-12-16 4 views
64

Ich versuche, die JSON-Serialisierungslandschaft in Ruby zu verstehen. Ich bin neu in Ruby.Ruby-Objekte und JSON-Serialisierung (ohne Rails)

Gibt es gute JSON-Serialisierungsoptionen, wenn Sie nicht mit Rails arbeiten?

das scheint zu sein, wo diese Antwort geht (Rails) How to convert a Ruby object to JSON

Die json Juwel scheint es so aussehen, wie Sie Ihre eigene to_json Methode zu schreiben. Ich war nicht in der Lage, zu_json zu arbeiten mit Arrays und Hashes (Dokumentation sagt, es funktioniert mit diesen) Gibt es einen Grund, die JSON-Edelstein nicht nur über das Objekt reflektieren und eine Standard-Serialisierungsstrategie verwenden? Ist das nicht wie to_yaml Werke (Erraten hier)

+2

Könnte klingen dumm, aber haben Sie eigentlich 'json'' erfordern? Ich arbeitete mit den JSON-Edelsteinen und sie arbeiteten wie ein Zauber. – DarkDust

Antwort

3
require 'json' 
{"foo" => "bar"}.to_json 
# => "{\"foo\":\"bar\"}" 
8

Wenn Rendering-Leistung entscheidend ist, können Sie auch bei yajl-ruby aussehen sollen, die die C yajl Bibliothek eine Bindung ist. Die Serialisierung API für diese eine wie folgt aussieht:

require 'yajl' 
Yajl::Encoder.encode({"foo" => "bar"}) #=> "{\"foo\":\"bar\"}" 
+0

Da ich in meinem nächsten Projekt mit vielen JSON-Daten arbeiten muss, kann dies mein Lebensretter sein. +1 – Ernest

96

Für die JSON-Bibliothek zur Verfügung stehen, können Sie libjson-ruby von Ihrem Paketmanager installieren.

die 'json' Bibliothek zu verwenden:

require 'json' 

Um ein Objekt zu JSON (diese 3 Möglichkeiten sind äquivalent) zu umwandeln:

JSON.dump object #returns a JSON string 
JSON.generate object #returns a JSON string 
object.to_json #returns a JSON string 

zu konvertieren JSON Text auf ein Objekt (das 2 Wege sind gleichwertig):

JSON.load string #returns an object 
JSON.parse string #returns an object 

Es wird etwas schwieriger für Objekte aus Ihren eigenen Klassen. Für die folgende Klasse erzeugt to_json so etwas wie "\"#<A:0xb76e5728>\"".

class A 
    def initialize a=[1,2,3], b='hello' 
     @a = a 
     @b = b 
    end 
end 

Dies ist wahrscheinlich nicht wünschenswert. Um Ihr Objekt als JSON serialisieren zu können, sollten Sie Ihre eigene to_json-Methode erstellen. Um damit zu gehen, wäre eine from_json Klassenmethode nützlich. Sie könnten Ihre Klasse wie so erweitern:

class A 
    def to_json 
     {'a' => @a, 'b' => @b}.to_json 
    end 
    def self.from_json string 
     data = JSON.load string 
     self.new data['a'], data['b'] 
    end 
end 

du von einem ‚JSONable‘ Klasse durch Erben automatisieren könnte:

class JSONable 
    def to_json 
     hash = {} 
     self.instance_variables.each do |var| 
      hash[var] = self.instance_variable_get var 
     end 
     hash.to_json 
    end 
    def from_json! string 
     JSON.load(string).each do |var, val| 
      self.instance_variable_set var, val 
     end 
    end 
end 

Dann Sie object.to_json verwenden können, um JSON zu serialise und object.from_json! string die gespeicherte kopieren Status, der als JSON-String für das Objekt gespeichert wurde.

+3

War auf der Suche nach einer Bibliothek, für die Sie nicht die Methode to_json für Klassen schreiben mussten. Gibt es eine Klasse, die Sie erben können, die Ihnen dies durch Reflexion gibt? und arbeitet an komplexen Objekten? – BuddyJoe

+0

Ich schaue mir an, wie der YAML-Code in der stdlib funktioniert, aber das ist ein bisschen viel für mich, an dieser Stelle zu grok. – BuddyJoe

+0

Hilft Ihnen die aktualisierte Antwort in dieser Hinsicht? – david4dev

6

Welche Version von Ruby verwenden Sie? ruby -v wird Ihnen sagen.

Wenn es 1.9.2 ist, JSON is included in the standard library.

Wenn Sie auf 1.8.etwas sind, dann tun Sie gem install json und es wird installiert.Dann im Code tun:

require 'rubygems' 
require 'json' 

dann to_json an ein Objekt anhängen und Sie sind gut zu gehen:

asdf = {'a' => 'b'} #=> {"a"=>"b"} 
asdf.to_json #=> "{"a":"b"}" 
+0

Wird es schneller als yajl? – Ernest

+0

Das ist für Sie mit [Benchmark] (http://ruby-doc.org/core/classes/Benchmark.html) zu bestimmen, nicht wahr? –

+1

Ich dachte, du weißt das vielleicht. Benchmarked und es ist langsamer: P Besonders bei der Codierung. – Ernest

1

Wenn Sie 1.9.2 verwenden oder oben können Sie Hashes konvertieren und Arrays zu verschachtelten JSON-Objekten, die nur to_json verwenden.

{a: [1,2,3], b: 4}.to_json 

In Rails können Sie to_json bei Active Record-Objekten aufrufen. Sie können passieren: include und: nur Parameter, die die Ausgabe steuern:

@user.to_json only: [:name, :email] 

Sie können auch to_json auf AR Beziehungen nennen, etwa so:

User.order("id DESC").limit(10).to_json 

Sie brauchen nichts zu importieren und Alles funktioniert genau so, wie Sie es sich wünschen.

9

Auschecken Oj. Es gibt Fehler, wenn es darum geht, ein altes Objekt in JSON zu konvertieren, aber Oj kann das tun.

require 'oj' 

class A 
    def initialize a=[1,2,3], b='hello' 
     @a = a 
     @b = b 
    end 
end 

a = A.new 
puts Oj::dump a, :indent => 2 

Diese Ausgänge:

{ 
    "^o":"A", 
    "a":[ 
    1, 
    2, 
    3 
    ], 
"b":"hello" 
} 

Beachten Sie, dass ^o die Klasse des Objekts zu bestimmen, verwendet wird, und ist es Deserialisierung zu unterstützen. Wegzulassen ^o verwenden :compat Modus:

puts Oj::dump a, :indent => 2, :mode => :compat 

Ausgang:

{ 
    "a":[ 
    1, 
    2, 
    3 
    ], 
    "b":"hello" 
} 
+0

'Oj' ist sehr kompatibel zum Ändern von Klassen und Deserialisieren ohne zusätzliche Fehler. +1 – ashes999

+1

Wie entferne ich diesen "^ oj" Wert? – neustart47

+1

@ neustart47: Ich habe meine Antwort bearbeitet, um zu zeigen, wie dies mit dem ': compat'-Modus gemacht werden kann. – Jimothy

0

Eigentlich gibt es ein Juwel namens Jsonable, https://github.com/treeder/jsonable. Es ist ziemlich süß.

+0

Jsonable scheint nicht mehr funktionstüchtig zu sein: Zuletzt aktualisiert im Jahr 2012, und der Beispielcode schlägt fehl - 'JSON.parse' gibt json zurück, kein Objekt. – ashes999

+0

Weiß nicht über die Beispiele, aber ich fand Jsonable perfekt für meinen Anwendungsfall: https://feedjira.herokuapp.com/ https://github.com/dentarg/feedjira.herokuapp.com/blob/464c27af9179dcb73898ca029883a648bccd67c2/feedjira .rb # L17 https://github.com/dentarg/feedjira.herokuapp.com/blob/464c27af9179dcb73898ca029883a648bccd67c2/monkey.rb – dentarg

+0

Vielleicht hängt es von Rails oder etwas anderem ab. Ich benutze gerade Ruby. – ashes999

1

Um die Build-in-Klassen (wie Array und Hash) zu erhalten as_json und to_json zu unterstützen, müssen Sie require 'json/add/core' (die readme für Details)

0

ich virtus verwendet. Wirklich leistungsstarkes Tool, mit dem Sie eine dynamische Ruby-Struktur basierend auf Ihren angegebenen Klassen erstellen können. Einfache DSL, möglich, um Objekte aus Ruby-Hashes zu erstellen, gibt es strikten Modus. Überprüfen Sie it aus.

4

Da ich viel gesucht ich ein Ruby-Objekt zu Json serialisiert:

require 'json' 

class User 
    attr_accessor :name, :age 

    def initialize(name, age) 
    @name = name 
    @age = age 
    end 

    def as_json(options={}) 
    { 
     name: @name, 
     age: @age 
    } 
    end 

    def to_json(*options) 
    as_json(*options).to_json(*options) 
    end 
end 

user = User.new("Foo Bar", 42) 
puts user.to_json #=> {"name":"Foo Bar","age":42} 
+1

Ich habe dies in eine Ruby-Datei kopiert und eingefügt, und es wurde ohne Probleme ausgeführt. Es könnte hilfreich sein, deine Antwort zu aktualisieren, um die Ausgabe einzuschließen: {"name": "Foo Bar", "Alter": 42} –

1

Jbuilder ist ein Juwel von Schienen Gemeinde gebaut. Aber es funktioniert gut in Nicht-Rails-Umgebungen und hat eine coole Reihe von Funktionen.

# suppose we have a sample object as below 
sampleObj.name #=> foo 
sampleObj.last_name #=> bar 

# using jbuilder we can convert it to json: 
Jbuilder.encode do |json| 
    json.name sampleObj.name 
    json.last_name sampleObj.last_name 
end #=> "{:\"name\" => \"foo\", :\"last_name\" => \"bar\"}"