Modul JSON
JavaScript Object Notation (JSON)
JSON ist ein leichtgewichtiges Datenformat.
Ein JSON-Wert ist einer der folgenden:
-
Text in doppelten Anführungszeichen:
"foo". -
Zahl:
1,1.0,2.0e2. -
Boolean:
true,false. -
Null:
null. -
Array: eine geordnete Liste von Werten, eingeschlossen von eckigen Klammern
["foo", 1, 1.0, 2.0e2, true, false, null]
-
Objekt: eine Sammlung von Schlüssel-Wert-Paaren, eingeschlossen von geschweiften Klammern; jeder Schlüssel ist Text in doppelten Anführungszeichen; die Werte können beliebige JSON-Werte sein
{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}
Ein JSON-Array oder -Objekt kann verschachtelte Arrays, Objekte und Skalare bis zu jeder Tiefe enthalten.
{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}
[{"foo": 0, "bar": 1}, ["baz", 2]]
Verwendung des Moduls JSON
Um das Modul JSON in Ihrem Code verfügbar zu machen, beginnen Sie mit
require 'json'
Alle Beispiele hier gehen davon aus, dass dies geschehen ist.
JSON parsen
Sie können einen String mit JSON-Daten mit einer der beiden Methoden parsen:
wobei
-
sourceein Ruby-Objekt ist. -
optsein Hash-Objekt ist, das Optionen enthält, die sowohl die erlaubten Eingaben als auch die Ausgabeformatierung steuern.
Der Unterschied zwischen den beiden Methoden besteht darin, dass JSON.parse! einige Prüfungen weglässt und für einige source-Daten möglicherweise nicht sicher ist; verwenden Sie sie nur für Daten aus vertrauenswürdigen Quellen. Verwenden Sie die sicherere Methode JSON.parse für weniger vertrauenswürdige Quellen.
JSON-Arrays parsen
Wenn source ein JSON-Array ist, gibt JSON.parse standardmäßig ein Ruby-Array zurück.
json = '["foo", 1, 1.0, 2.0e2, true, false, null]' ruby = JSON.parse(json) ruby # => ["foo", 1, 1.0, 200.0, true, false, nil] ruby.class # => Array
Das JSON-Array kann verschachtelte Arrays, Objekte und Skalare bis zu jeder Tiefe enthalten.
json = '[{"foo": 0, "bar": 1}, ["baz", 2]]' JSON.parse(json) # => [{"foo"=>0, "bar"=>1}, ["baz", 2]]
JSON-Objekte parsen
Wenn die Quelle ein JSON-Objekt ist, gibt JSON.parse standardmäßig einen Ruby-Hash zurück.
json = '{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}' ruby = JSON.parse(json) ruby # => {"a"=>"foo", "b"=>1, "c"=>1.0, "d"=>200.0, "e"=>true, "f"=>false, "g"=>nil} ruby.class # => Hash
Das JSON-Objekt kann verschachtelte Arrays, Objekte und Skalare bis zu jeder Tiefe enthalten.
json = '{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}' JSON.parse(json) # => {"foo"=>{"bar"=>1, "baz"=>2}, "bat"=>[0, 1, 2]}
JSON-Skalare parsen
Wenn die Quelle ein JSON-Skalar ist (kein Array oder Objekt), gibt JSON.parse einen Ruby-Skalar zurück.
String
ruby = JSON.parse('"foo"') ruby # => 'foo' ruby.class # => String
Integer
ruby = JSON.parse('1') ruby # => 1 ruby.class # => Integer
Float
ruby = JSON.parse('1.0') ruby # => 1.0 ruby.class # => Float ruby = JSON.parse('2.0e2') ruby # => 200 ruby.class # => Float
Boolean
ruby = JSON.parse('true') ruby # => true ruby.class # => TrueClass ruby = JSON.parse('false') ruby # => false ruby.class # => FalseClass
Null
ruby = JSON.parse('null') ruby # => nil ruby.class # => NilClass
Parsing-Optionen
Eingabeoptionen
Die Option max_nesting (Integer) gibt die maximal erlaubte Verschachtelungstiefe an; Standardwert ist 100; geben Sie false an, um die Tiefenprüfung zu deaktivieren.
Mit dem Standardwert false
source = '[0, [1, [2, [3]]]]' ruby = JSON.parse(source) ruby # => [0, [1, [2, [3]]]]
Zu tief
# Raises JSON::NestingError (nesting of 2 is too deep): JSON.parse(source, {max_nesting: 1})
Ungültiger Wert
# Raises TypeError (wrong argument type Symbol (expected Fixnum)): JSON.parse(source, {max_nesting: :foo})
Die Option allow_duplicate_key gibt an, ob doppelte Schlüssel in Objekten ignoriert oder einen Fehler auslösen sollen.
Wenn nicht angegeben
# The last value is used and a deprecation warning emitted.
JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
# warning: detected duplicate keys in JSON object.
# This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
Wenn auf 'true' gesetzt
# The last value is used.
JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
Wenn auf 'false' gesetzt, der zukünftige Standardwert
JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError)
Die Option allow_nan (Boolean) gibt an, ob NaN, Infinity und MinusInfinity in source erlaubt sind; Standardwert ist false.
Mit dem Standardwert false
# Raises JSON::ParserError (225: unexpected token at '[NaN]'): JSON.parse('[NaN]') # Raises JSON::ParserError (232: unexpected token at '[Infinity]'): JSON.parse('[Infinity]') # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'): JSON.parse('[-Infinity]')
Erlauben
source = '[NaN, Infinity, -Infinity]' ruby = JSON.parse(source, {allow_nan: true}) ruby # => [NaN, Infinity, -Infinity]
Die Option allow_trailing_comma (Boolean) gibt an, ob nachgestellte Kommas in Objekten und Arrays erlaubt sind; Standardwert ist false.
Mit dem Standardwert false
JSON.parse('[1,]') # unexpected character: ']' at line 1 column 4 (JSON::ParserError)
Wenn aktiviert
JSON.parse('[1,]', allow_trailing_comma: true) # => [1]
Ausgabeoptionen
Die Option freeze (Boolean) gibt an, ob die zurückgegebenen Objekte "eingefroren" (unveränderlich) sein sollen; Standardwert ist false.
Die Option symbolize_names (Boolean) gibt an, ob die Schlüssel der zurückgegebenen Hashes Symbole sein sollen; Standardwert ist false (verwende Strings).
Mit dem Standardwert false
source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' ruby = JSON.parse(source) ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
Symbole verwenden
ruby = JSON.parse(source, {symbolize_names: true}) ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
Die Option object_class (Class) gibt die Ruby-Klasse an, die für jedes JSON-Objekt verwendet werden soll; Standardwert ist Hash.
Mit dem Standardwert, Hash
source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' ruby = JSON.parse(source) ruby.class # => Hash
Klasse OpenStruct verwenden
ruby = JSON.parse(source, {object_class: OpenStruct}) ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
Die Option array_class (Class) gibt die Ruby-Klasse an, die für jedes JSON-Array verwendet werden soll; Standardwert ist Array.
Mit dem Standardwert, Array
source = '["foo", 1.0, true, false, null]' ruby = JSON.parse(source) ruby.class # => Array
Klasse Set verwenden
ruby = JSON.parse(source, {array_class: Set}) ruby # => #<Set: {"foo", 1.0, true, false, nil}>
Die Option create_additions (Boolean) gibt an, ob JSON-Erweiterungen beim Parsen verwendet werden sollen. Siehe JSON-Erweiterungen.
JSON generieren
Um einen Ruby-String mit JSON-Daten zu generieren, verwenden Sie die Methode JSON.generate(source, opts), wobei
-
sourceein Ruby-Objekt ist. -
optsein Hash-Objekt ist, das Optionen enthält, die sowohl die erlaubten Eingaben als auch die Ausgabeformatierung steuern.
JSON aus Arrays generieren
Wenn die Quelle ein Ruby-Array ist, gibt JSON.generate einen String mit einem JSON-Array zurück.
ruby = [0, 's', :foo] json = JSON.generate(ruby) json # => '[0,"s","foo"]'
Das Ruby-Array kann verschachtelte Arrays, Hashes und Skalare bis zu jeder Tiefe enthalten.
ruby = [0, [1, 2], {foo: 3, bar: 4}] json = JSON.generate(ruby) json # => '[0,[1,2],{"foo":3,"bar":4}]'
JSON aus Hashes generieren
Wenn die Quelle ein Ruby-Hash ist, gibt JSON.generate einen String mit einem JSON-Objekt zurück.
ruby = {foo: 0, bar: 's', baz: :bat} json = JSON.generate(ruby) json # => '{"foo":0,"bar":"s","baz":"bat"}'
Das Ruby-Hash-Array kann verschachtelte Arrays, Hashes und Skalare bis zu jeder Tiefe enthalten.
ruby = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad} json = JSON.generate(ruby) json # => '{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}'
JSON aus anderen Objekten generieren
Wenn die Quelle weder ein Array noch ein Hash ist, hängen die generierten JSON-Daten von der Klasse der Quelle ab.
Wenn die Quelle eine Ruby-Ganzzahl oder -Gleitkommazahl ist, gibt JSON.generate einen String mit einer JSON-Zahl zurück.
JSON.generate(42) # => '42' JSON.generate(0.42) # => '0.42'
Wenn die Quelle ein Ruby-String ist, gibt JSON.generate einen String mit einem JSON-String (mit doppelten Anführungszeichen) zurück.
JSON.generate('A string') # => '"A string"'
Wenn die Quelle true, false oder nil ist, gibt JSON.generate einen String mit dem entsprechenden JSON-Token zurück.
JSON.generate(true) # => 'true' JSON.generate(false) # => 'false' JSON.generate(nil) # => 'null'
Wenn die Quelle keine der obigen ist, gibt JSON.generate einen String mit einer JSON-String-Repräsentation der Quelle zurück.
JSON.generate(:foo) # => '"foo"' JSON.generate(Complex(0, 0)) # => '"0+0i"' JSON.generate(Dir.new('.')) # => '"#<Dir>"'
Generierungsoptionen
Eingabeoptionen
Die Option allow_nan (Boolean) gibt an, ob NaN, Infinity und -Infinity generiert werden dürfen; Standardwert ist false.
Mit dem Standardwert false
# Raises JSON::GeneratorError (920: NaN not allowed in JSON): JSON.generate(JSON::NaN) # Raises JSON::GeneratorError (917: Infinity not allowed in JSON): JSON.generate(JSON::Infinity) # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON): JSON.generate(JSON::MinusInfinity)
Erlauben
ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity] JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
Die Option allow_duplicate_key (Boolean) gibt an, ob Hashes mit doppelten Schlüsseln erlaubt sein sollen oder einen Fehler erzeugen. Standard ist die Ausgabe einer Deprecation-Warnung.
Mit dem Standardwert (nicht gesetzt)
Warning[:deprecated] = true JSON.generate({ foo: 1, "foo" => 2 }) # warning: detected duplicate key "foo" in {foo: 1, "foo" => 2}. # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true` # => '{"foo":1,"foo":2}'
Mit false
JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: false) # detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
In Version 3.0 wird false zum Standard.
Die Option max_nesting (Integer) gibt die maximale Verschachtelungstiefe in obj an; Standardwert ist 100.
Mit dem Standardwert, 100
obj = [[[[[[0]]]]]] JSON.generate(obj) # => '[[[[[[0]]]]]]'
Zu tief
# Raises JSON::NestingError (nesting of 2 is too deep): JSON.generate(obj, max_nesting: 2)
Escaping-Optionen
Die Optionen script_safe (Boolean) geben an, ob '\u2028', '\u2029' und '/' so maskiert werden sollen, dass das JSON-Objekt sicher in Skript-Tags eingefügt werden kann.
Die Option ascii_only (Boolean) gibt an, ob alle Zeichen außerhalb des ASCII-Bereichs maskiert werden sollen.
Ausgabeoptionen
Die Standard-Formatierungsoptionen erzeugen die kompaktesten JSON-Daten, alles auf einer Zeile und ohne Leerzeichen.
Sie können diese Formatierungsoptionen verwenden, um JSON-Daten in einem offeneren Format mit Leerzeichen zu generieren. Siehe auch JSON.pretty_generate.
-
Die Option
array_nl(String) gibt einen String (normalerweise einen Zeilenumbruch) an, der nach jedem JSON-Array eingefügt werden soll; Standardwert ist der leere String,''. -
Die Option
object_nl(String) gibt einen String (normalerweise einen Zeilenumbruch) an, der nach jedem JSON-Objekt eingefügt werden soll; Standardwert ist der leere String,''. -
Die Option
indent(String) gibt den String (normalerweise Leerzeichen) an, der für die Einrückung verwendet werden soll; Standardwert ist der leere String,''; hat keine Auswirkung, es sei denn, die Optionenarray_nloderobject_nlgeben Zeilenumbrüche an. -
Die Option
space(String) gibt einen String (normalerweise ein Leerzeichen) an, der nach dem Doppelpunkt in jedem Schlüssel-Wert-Paar eines JSON-Objekts eingefügt werden soll; Standardwert ist der leere String,''. -
Die Option
space_before(String) gibt einen String (normalerweise ein Leerzeichen) an, der vor dem Doppelpunkt in jedem Schlüssel-Wert-Paar eines JSON-Objekts eingefügt werden soll; Standardwert ist der leere String,''.
In diesem Beispiel wird obj zuerst verwendet, um die kürzesten JSON-Daten (ohne Leerzeichen) zu generieren, und dann erneut mit allen angegebenen Formatierungsoptionen.
obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}} json = JSON.generate(obj) puts 'Compact:', json opts = { array_nl: "\n", object_nl: "\n", indent: ' ', space_before: ' ', space: ' ' } puts 'Open:', JSON.generate(obj, opts)
Ausgabe
Compact:
{"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
Open:
{
"foo" : [
"bar",
"baz"
],
"bat" : {
"bam" : 0,
"bad" : 1
}
}
JSON-Erweiterungen
Beachten Sie, dass JSON-Erweiterungen nur mit vertrauenswürdigen Daten verwendet werden dürfen und veraltet sind.
Wenn Sie ein Nicht-String-Objekt von Ruby nach JSON und zurück "roundtrippen", erhalten Sie einen neuen String anstelle des ursprünglichen Objekts.
ruby0 = Range.new(0, 2) json = JSON.generate(ruby0) json # => '0..2"' ruby1 = JSON.parse(json) ruby1 # => '0..2' ruby1.class # => String
Sie können JSON-Erweiterungen verwenden, um das ursprüngliche Objekt zu erhalten. Die Erweiterung ist eine Erweiterung einer Ruby-Klasse, sodass
-
JSON.generate speichert mehr Informationen im JSON-String.
-
JSON.parse, aufgerufen mit der Option
create_additions, verwendet diese Informationen, um ein korrektes Ruby-Objekt zu erstellen.
Dieses Beispiel zeigt einen Range, der in JSON generiert und zurück nach Ruby geparst wird, sowohl ohne als auch mit der Erweiterung für Range.
ruby = Range.new(0, 2) # This passage does not use the addition for Range. json0 = JSON.generate(ruby) ruby0 = JSON.parse(json0) # This passage uses the addition for Range. require 'json/add/range' json1 = JSON.generate(ruby) ruby1 = JSON.parse(json1, create_additions: true) # Make a nice display. display = <<~EOT Generated JSON: Without addition: #{json0} (#{json0.class}) With addition: #{json1} (#{json1.class}) Parsed JSON: Without addition: #{ruby0.inspect} (#{ruby0.class}) With addition: #{ruby1.inspect} (#{ruby1.class}) EOT puts display
Diese Ausgabe zeigt die unterschiedlichen Ergebnisse.
Generated JSON:
Without addition: "0..2" (String)
With addition: {"json_class":"Range","a":[0,2,false]} (String)
Parsed JSON:
Without addition: "0..2" (String)
With addition: 0..2 (Range)
Das JSON-Modul enthält Erweiterungen für bestimmte Klassen. Sie können auch benutzerdefinierte Erweiterungen erstellen. Siehe Benutzerdefinierte JSON-Erweiterungen.
Integrierte Erweiterungen
Das JSON-Modul enthält Erweiterungen für bestimmte Klassen. Um eine Erweiterung zu verwenden, requiren Sie ihre Quelle.
-
BigDecimal:
require 'json/add/bigdecimal' -
Complex:
require 'json/add/complex' -
Date:
require 'json/add/date' -
DateTime:
require 'json/add/date_time' -
Exception:
require 'json/add/exception' -
OpenStruct:
require 'json/add/ostruct' -
Range:
require 'json/add/range' -
Rational:
require 'json/add/rational' -
Regexp:
require 'json/add/regexp' -
Set:
require 'json/add/set' -
Struct:
require 'json/add/struct' -
Symbol:
require 'json/add/symbol' -
Time:
require 'json/add/time'
Um die Zeichensetzung zu reduzieren, zeigen die folgenden Beispiele das generierte JSON über puts anstelle des üblichen inspect.
BigDecimal
require 'json/add/bigdecimal' ruby0 = BigDecimal(0) # 0.0 json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"} ruby1 = JSON.parse(json, create_additions: true) # 0.0 ruby1.class # => BigDecimal
Complex
require 'json/add/complex' ruby0 = Complex(1+0i) # 1+0i json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0} ruby1 = JSON.parse(json, create_additions: true) # 1+0i ruby1.class # Complex
Date
require 'json/add/date' ruby0 = Date.today # 2020-05-02 json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0} ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 ruby1.class # Date
DateTime
require 'json/add/date_time' ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00 json = JSON.generate(ruby0) # {"json_class":"DateTime","y":2020,"m":5,"d":2,"H":10,"M":38,"S":13,"of":"-5/24","sg":2299161.0} ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00 ruby1.class # DateTime
Exception (und seine Unterklassen, einschließlich RuntimeError)
require 'json/add/exception' ruby0 = Exception.new('A message') # A message json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null} ruby1 = JSON.parse(json, create_additions: true) # A message ruby1.class # Exception ruby0 = RuntimeError.new('Another message') # Another message json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null} ruby1 = JSON.parse(json, create_additions: true) # Another message ruby1.class # RuntimeError
OpenStruct
require 'json/add/ostruct' ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #<OpenStruct name="Matz", language="Ruby"> json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}} ruby1 = JSON.parse(json, create_additions: true) # #<OpenStruct name="Matz", language="Ruby"> ruby1.class # OpenStruct
Range
require 'json/add/range' ruby0 = Range.new(0, 2) # 0..2 json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]} ruby1 = JSON.parse(json, create_additions: true) # 0..2 ruby1.class # Range
Rational
require 'json/add/rational' ruby0 = Rational(1, 3) # 1/3 json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3} ruby1 = JSON.parse(json, create_additions: true) # 1/3 ruby1.class # Rational
Regexp
require 'json/add/regexp' ruby0 = Regexp.new('foo') # (?-mix:foo) json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"} ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo) ruby1.class # Regexp
Set
require 'json/add/set' ruby0 = Set.new([0, 1, 2]) # #<Set: {0, 1, 2}> json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]} ruby1 = JSON.parse(json, create_additions: true) # #<Set: {0, 1, 2}> ruby1.class # Set
Struct
require 'json/add/struct' Customer = Struct.new(:name, :address) # Customer ruby0 = Customer.new("Dave", "123 Main") # #<struct Customer name="Dave", address="123 Main"> json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]} ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main"> ruby1.class # Customer
Symbol
require 'json/add/symbol' ruby0 = :foo # foo json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"} ruby1 = JSON.parse(json, create_additions: true) # foo ruby1.class # Symbol
Time
require 'json/add/time' ruby0 = Time.now # 2020-05-02 11:28:26 -0500 json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000} ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500 ruby1.class # Time
Benutzerdefinierte JSON-Erweiterungen
Zusätzlich zu den bereitgestellten JSON-Erweiterungen können Sie eigene JSON-Erweiterungen erstellen, entweder für integrierte Ruby-Klassen oder für benutzerdefinierte Klassen.
Hier ist eine benutzerdefinierte Klasse Foo.
class Foo attr_accessor :bar, :baz def initialize(bar, baz) self.bar = bar self.baz = baz end end
Hier ist die JSON-Erweiterung dafür.
# Extend class Foo with JSON addition. class Foo # Serialize Foo object with its class name and arguments def to_json(*args) { JSON.create_id => self.class.name, 'a' => [ bar, baz ] }.to_json(*args) end # Deserialize JSON string by constructing new Foo object with arguments. def self.json_create(object) new(*object['a']) end end
Demonstration
require 'json' # This Foo object has no custom addition. foo0 = Foo.new(0, 1) json0 = JSON.generate(foo0) obj0 = JSON.parse(json0) # Lood the custom addition. require_relative 'foo_addition' # This foo has the custom addition. foo1 = Foo.new(0, 1) json1 = JSON.generate(foo1) obj1 = JSON.parse(json1, create_additions: true) # Make a nice display. display = <<~EOT Generated JSON: Without custom addition: #{json0} (#{json0.class}) With custom addition: #{json1} (#{json1.class}) Parsed JSON: Without custom addition: #{obj0.inspect} (#{obj0.class}) With custom addition: #{obj1.inspect} (#{obj1.class}) EOT puts display
Ausgabe
Generated JSON:
Without custom addition: "#<Foo:0x0000000006534e80>" (String)
With custom addition: {"json_class":"Foo","a":[0,1]} (String)
Parsed JSON:
Without custom addition: "#<Foo:0x0000000006534e80>" (String)
With custom addition: #<Foo:0x0000000006473bb8 @bar=0, @baz=1> (Foo)
Constants
- Fragment
-
FragmenteinesJSON-Dokuments, das unverändert übernommen werden soll.fragment = JSON::Fragment.new("[1, 2, 3]") JSON.generate({ count: 3, items: fragments })
Dies ermöglicht das einfache Zusammenfügen mehrerer
JSON-Fragmente, die irgendwo gespeichert wurden, ohne sie parsen zu müssen oder auf String-Interpolation zurückzugreifen.Hinweis: Es wird keine Validierung des bereitgestellten Strings durchgeführt. Es liegt in der Verantwortung des Aufrufers, sicherzustellen, dass der String gültiges
JSONenthält. - Infinity
- JSON_LOADED
- MinusInfinity
- NaN
- PARSE_L_OPTIONS
- PRETTY_GENERATE_OPTIONS
- VERSION
Attribute
Öffentliche Klassenmethoden
Source
# File ext/json/lib/json/common.rb, line 132 def [](object, opts = nil) if object.is_a?(String) return JSON.parse(object, opts) elsif object.respond_to?(:to_str) str = object.to_str if str.is_a?(String) return JSON.parse(str, opts) end end JSON.generate(object, opts) end
Wenn object ein String ist, ruft JSON.parse mit object und opts auf (siehe Methode parse).
json = '[0, 1, null]' JSON[json]# => [0, 1, nil]
Andernfalls ruft JSON.generate mit object und opts auf (siehe Methode generate).
ruby = [0, 1, nil] JSON[ruby] # => '[0,1,null]'
Source
# File ext/json/lib/json/common.rb, line 234 def self.create_id Thread.current[:"JSON.create_id"] || 'json_class' end
Gibt die aktuelle Erstellungs-ID zurück. Siehe auch JSON.create_id=.
Source
# File ext/json/lib/json/common.rb, line 228 def self.create_id=(new_value) Thread.current[:"JSON.create_id"] = new_value.dup.freeze end
Legt die Erstellungs-ID fest, die bestimmt, ob der json_create Hook einer Klasse aufgerufen werden soll; Anfangswert ist json_class.
JSON.create_id # => 'json_class'
Private Klassenmethoden
Source
# File ext/json/lib/json/common.rb, line 203 def deprecated_singleton_attr_accessor(*attrs) args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : "" attrs.each do |attr| singleton_class.class_eval <<~RUBY def #{attr} warn "JSON.#{attr} is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args} @#{attr} end def #{attr}=(val) warn "JSON.#{attr}= is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args} @#{attr} = val end def _#{attr} @#{attr} end RUBY end end
Source
# File ext/json/lib/json/common.rb, line 185 def on_mixed_keys_hash(hash, do_raise) set = {} hash.each_key do |key| key_str = key.to_s if set[key_str] message = "detected duplicate key #{key_str.inspect} in #{hash.inspect}" if do_raise raise GeneratorError, message else deprecation_warning("#{message}.\nThis will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`") end else set[key_str] = true end end end
Wird von der Erweiterung aufgerufen, wenn ein Hash sowohl String- als auch Symbolschlüssel hat.
Öffentliche Instanzmethoden
Source
# File ext/json/lib/json/common.rb, line 930 def dump(obj, anIO = nil, limit = nil, kwargs = nil) if kwargs.nil? if limit.nil? if anIO.is_a?(Hash) kwargs = anIO anIO = nil end elsif limit.is_a?(Hash) kwargs = limit limit = nil end end unless anIO.nil? if anIO.respond_to?(:to_io) anIO = anIO.to_io elsif limit.nil? && !anIO.respond_to?(:write) anIO, limit = nil, anIO end end opts = JSON._dump_default_options opts = opts.merge(:max_nesting => limit) if limit opts = opts.merge(kwargs) if kwargs begin State.generate(obj, opts, anIO) rescue JSON::NestingError raise ArgumentError, "exceed depth limit" end end
Gibt obj als JSON-String aus, d.h. ruft generate für das Objekt auf und gibt das Ergebnis zurück.
Die Standardoptionen können über die Methode JSON.dump_default_options geändert werden.
-
Das Argument
io, falls vorhanden, sollte auf die Methodewritereagieren; der JSON-String wird iniogeschrieben undiozurückgegeben. Wennionicht gegeben ist, wird der JSON-String zurückgegeben. -
Das Argument
limit, falls vorhanden, wird anJSON.generateals Optionmax_nestingübergeben.
Wenn das Argument io nicht gegeben ist, wird der aus obj generierte JSON-String zurückgegeben.
obj = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad} json = JSON.dump(obj) json # => "{\"foo\":[0,1],\"bar\":{\"baz\":2,\"bat\":3},\"bam\":\"bad\"}"
Wenn das Argument io gegeben ist, wird der JSON-String in io geschrieben und io zurückgegeben.
path = 't.json' File.open(path, 'w') do |file| JSON.dump(obj, file) end # => #<File:t.json (closed)> puts File.read(path)
Ausgabe
{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
Source
# File ext/json/lib/json/common.rb, line 460 def fast_generate(obj, opts = nil) if RUBY_VERSION >= "3.0" warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated else warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1 end generate(obj, opts) end
Die Argumente obj und opts sind hier die gleichen wie die Argumente obj und opts in JSON.generate.
Standardmäßig werden JSON-Daten generiert, ohne auf zirkuläre Referenzen in obj zu prüfen (Option max_nesting auf false gesetzt, deaktiviert).
Löst eine Ausnahme aus, wenn obj zirkuläre Referenzen enthält.
a = []; b = []; a.push(b); b.push(a) # Raises SystemStackError (stack level too deep): JSON.fast_generate(a)
Source
# File ext/json/lib/json/common.rb, line 439 def generate(obj, opts = nil) if State === opts opts.generate(obj) else State.generate(obj, opts, nil) end end
Gibt einen String mit den generierten JSON-Daten zurück.
Siehe auch JSON.pretty_generate.
Das Argument obj ist das Ruby-Objekt, das in JSON konvertiert werden soll.
Das Argument opts, falls gegeben, enthält einen Hash von Optionen für die Generierung. Siehe Generierungsoptionen.
Wenn obj ein Array ist, wird ein String mit einem JSON-Array zurückgegeben.
obj = ["foo", 1.0, true, false, nil] json = JSON.generate(obj) json # => '["foo",1.0,true,false,null]'
Wenn obj ein Hash ist, wird ein String mit einem JSON-Objekt zurückgegeben.
obj = {foo: 0, bar: 's', baz: :bat} json = JSON.generate(obj) json # => '{"foo":0,"bar":"s","baz":"bat"}'
Beispiele für die Generierung aus anderen Ruby-Objekten finden Sie unter JSON aus anderen Objekten generieren.
Löst eine Ausnahme aus, wenn eine Formatierungsoption keine Zeichenkette ist.
Löst eine Ausnahme aus, wenn obj zirkuläre Referenzen enthält.
a = []; b = []; a.push(b); b.push(a) # Raises JSON::NestingError (nesting of 100 is too deep): JSON.generate(a)
Source
# File ext/json/lib/json/common.rb, line 854 def load(source, proc = nil, options = nil) if proc && options.nil? && proc.is_a?(Hash) options = proc proc = nil end opts = if options.nil? if proc && proc.is_a?(Hash) options, proc = proc, nil options else _load_default_options end else _load_default_options.merge(options) end unless source.is_a?(String) if source.respond_to? :to_str source = source.to_str elsif source.respond_to? :to_io source = source.to_io.read elsif source.respond_to?(:read) source = source.read end end if opts[:allow_blank] && (source.nil? || source.empty?) source = 'null' end if proc opts = opts.dup opts[:on_load] = proc.to_proc end parse(source, opts) end
Gibt die Ruby-Objekte zurück, die durch Parsen der gegebenen source erstellt wurden.
ACHTUNG: Diese Methode ist zur Serialisierung von Daten aus vertrauenswürdigen Benutzereingaben gedacht, z. B. von Ihrem eigenen Datenbankserver oder von Ihnen kontrollierten Clients. Es kann gefährlich sein, nicht vertrauenswürdigen Benutzern zu erlauben, JSON-Quellen daran zu übergeben. Wenn Sie sie verwenden müssen, verwenden Sie stattdessen JSON.unsafe_load, um dies deutlich zu machen.
Seit JSON Version 2.8.0 gibt load eine Deprecation-Warnung aus, wenn ein nicht-nativer Typ deserialisiert wird, ohne dass `create_additions` explizit aktiviert wurde. In JSON Version 3.0 wird `load` standardmäßig `create_additions` deaktiviert haben.
-
Das Argument
sourcemuss ein String sein oder in einen String konvertierbar sein.-
Wenn
sourcedie Instanzmethodeto_strimplementiert, wirdsource.to_strzur Quelle. -
Wenn
sourcedie Instanzmethodeto_ioimplementiert, wirdsource.to_io.readzur Quelle. -
Wenn
sourcedie Instanzmethodereadimplementiert, wirdsource.readzur Quelle. -
Wenn beides zutrifft, wird die Quelle zum String
'null'.-
Die Option
allow_blankgibt einen Wahrheitsschätzer an. -
Die Quelle, wie oben definiert, ist
niloder der leere String''.
-
-
Andernfalls bleibt
sourcedie Quelle.
-
-
Das Argument
proc, falls gegeben, muss ein Proc sein, das ein Argument akzeptiert. Es wird rekursiv mit jedem Ergebnis (in Tiefensuche) aufgerufen. Details siehe unten. -
Das Argument
opts, falls gegeben, enthält einen Hash von Optionen für das Parsen. Siehe Parsing-Optionen. Die Standardoptionen können über die Methode JSON.load_default_options= geändert werden.
Wenn kein proc gegeben ist, wird source wie oben modifiziert und das Ergebnis von parse(source, opts) zurückgegeben; siehe parse.
Quelle für die folgenden Beispiele.
source = <<~JSON { "name": "Dave", "age" :40, "hats": [ "Cattleman's", "Panama", "Tophat" ] } JSON
Einen String laden
ruby = JSON.load(source) ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
Ein IO-Objekt laden
require 'stringio' object = JSON.load(StringIO.new(source)) object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
Ein File-Objekt laden
path = 't.json' File.write(path, source) File.open(path) do |file| JSON.load(file) end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
Wenn proc gegeben ist
-
Modifiziert
sourcewie oben. -
Erhält das
resultdurch Aufruf vonparse(source, opts). -
Ruft
proc(result)rekursiv auf. -
Gibt das Endergebnis zurück.
Beispiel
require 'json' # Some classes for the example. class Base def initialize(attributes) @attributes = attributes end end class User < Base; end class Account < Base; end class Admin < Base; end # The JSON source. json = <<-EOF { "users": [ {"type": "User", "username": "jane", "email": "jane@example.com"}, {"type": "User", "username": "john", "email": "john@example.com"} ], "accounts": [ {"account": {"type": "Account", "paid": true, "account_id": "1234"}}, {"account": {"type": "Account", "paid": false, "account_id": "1235"}} ], "admins": {"type": "Admin", "password": "0wn3d"} } EOF # Deserializer method. def deserialize_obj(obj, safe_types = %w(User Account Admin)) type = obj.is_a?(Hash) && obj["type"] safe_types.include?(type) ? Object.const_get(type).new(obj) : obj end # Call to JSON.load ruby = JSON.load(json, proc {|obj| case obj when Hash obj.each {|k, v| obj[k] = deserialize_obj v } when Array obj.map! {|v| deserialize_obj v } end obj }) pp ruby
Ausgabe
{"users"=>
[#<User:0x00000000064c4c98
@attributes=
{"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
#<User:0x00000000064c4bd0
@attributes=
{"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
"accounts"=>
[{"account"=>
#<Account:0x00000000064c4928
@attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
{"account"=>
#<Account:0x00000000064c4680
@attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
"admins"=>
#<Admin:0x00000000064c41f8
@attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
Source
# File ext/json/lib/json/common.rb, line 388 def load_file(filespec, opts = nil) parse(File.read(filespec, encoding: Encoding::UTF_8), opts) end
Source
# File ext/json/lib/json/common.rb, line 399 def load_file!(filespec, opts = nil) parse!(File.read(filespec, encoding: Encoding::UTF_8), opts) end
Source
# File ext/json/lib/json/common.rb, line 351 def parse(source, opts = nil) opts = ParserOptions.prepare(opts) unless opts.nil? Parser.parse(source, opts) end
Gibt die Ruby-Objekte zurück, die durch Parsen der gegebenen source erstellt wurden.
Das Argument source enthält den zu parsierenden String.
Das Argument opts, falls gegeben, enthält einen Hash von Optionen für das Parsen. Siehe Parsing-Optionen.
Wenn source ein JSON-Array ist, wird ein Ruby-Array zurückgegeben.
source = '["foo", 1.0, true, false, null]' ruby = JSON.parse(source) ruby # => ["foo", 1.0, true, false, nil] ruby.class # => Array
Wenn source ein JSON-Objekt ist, wird ein Ruby-Hash zurückgegeben.
source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' ruby = JSON.parse(source) ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil} ruby.class # => Hash
Beispiele für das Parsen aller JSON-Datentypen finden Sie unter JSON parsen.
Verschachtelte JSON-Objekte parsen.
source = <<~JSON { "name": "Dave", "age" :40, "hats": [ "Cattleman's", "Panama", "Tophat" ] } JSON ruby = JSON.parse(source) ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
Löst eine Ausnahme aus, wenn source kein gültiges JSON ist.
# Raises JSON::ParserError (783: unexpected token at ''): JSON.parse('')
Source
# File ext/json/lib/json/common.rb, line 373 def parse!(source, opts = nil) if opts.nil? parse(source, PARSE_L_OPTIONS) else parse(source, PARSE_L_OPTIONS.merge(opts)) end end
Ruft auf.
parse(source, opts)
mit source und möglicherweise modifizierten opts.
Unterschiede zu JSON.parse
-
Die Option
max_nestingist, wenn sie nicht angegeben ist, standardmäßigfalse, was die Prüfung der Verschachtelungstiefe deaktiviert. -
Die Option
allow_nanist, wenn sie nicht angegeben ist, standardmäßigtrue.
Source
# File ext/json/lib/json/common.rb, line 507 def pretty_generate(obj, opts = nil) return opts.generate(obj) if State === opts options = PRETTY_GENERATE_OPTIONS if opts unless opts.is_a?(Hash) if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end end options = options.merge(opts) end State.generate(obj, options, nil) end
Die Argumente obj und opts sind hier die gleichen wie die Argumente obj und opts in JSON.generate.
Standardoptionen sind:
{
indent: ' ', # Two spaces
space: ' ', # One space
array_nl: "\n", # Newline
object_nl: "\n" # Newline
}
Beispiel
obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}} json = JSON.pretty_generate(obj) puts json
Ausgabe
{
"foo": [
"bar",
"baz"
],
"bat": {
"bam": 0,
"bad": 1
}
}
Source
# File ext/json/lib/json/common.rb, line 683 def unsafe_load(source, proc = nil, options = nil) opts = if options.nil? if proc && proc.is_a?(Hash) options, proc = proc, nil options else _unsafe_load_default_options end else _unsafe_load_default_options.merge(options) end unless source.is_a?(String) if source.respond_to? :to_str source = source.to_str elsif source.respond_to? :to_io source = source.to_io.read elsif source.respond_to?(:read) source = source.read end end if opts[:allow_blank] && (source.nil? || source.empty?) source = 'null' end if proc opts = opts.dup opts[:on_load] = proc.to_proc end parse(source, opts) end
Gibt die Ruby-Objekte zurück, die durch Parsen der gegebenen source erstellt wurden.
ACHTUNG: Diese Methode ist zur Serialisierung von Daten aus vertrauenswürdigen Benutzereingaben gedacht, z. B. von Ihrem eigenen Datenbankserver oder von Ihnen kontrollierten Clients. Es kann gefährlich sein, nicht vertrauenswürdigen Benutzern zu erlauben, JSON-Quellen daran zu übergeben.
-
Das Argument
sourcemuss ein String sein oder in einen String konvertierbar sein.-
Wenn
sourcedie Instanzmethodeto_strimplementiert, wirdsource.to_strzur Quelle. -
Wenn
sourcedie Instanzmethodeto_ioimplementiert, wirdsource.to_io.readzur Quelle. -
Wenn
sourcedie Instanzmethodereadimplementiert, wirdsource.readzur Quelle. -
Wenn beides zutrifft, wird die Quelle zum String
'null'.-
Die Option
allow_blankgibt einen Wahrheitsschätzer an. -
Die Quelle, wie oben definiert, ist
niloder der leere String''.
-
-
Andernfalls bleibt
sourcedie Quelle.
-
-
Das Argument
proc, falls gegeben, muss ein Proc sein, das ein Argument akzeptiert. Es wird rekursiv mit jedem Ergebnis (in Tiefensuche) aufgerufen. Details siehe unten. -
Das Argument
opts, falls gegeben, enthält einen Hash von Optionen für das Parsen. Siehe Parsing-Optionen. Die Standardoptionen können über die Methode JSON.unsafe_load_default_options= geändert werden.
Wenn kein proc gegeben ist, wird source wie oben modifiziert und das Ergebnis von parse(source, opts) zurückgegeben; siehe parse.
Quelle für die folgenden Beispiele.
source = <<~JSON { "name": "Dave", "age" :40, "hats": [ "Cattleman's", "Panama", "Tophat" ] } JSON
Einen String laden
ruby = JSON.unsafe_load(source) ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
Ein IO-Objekt laden
require 'stringio' object = JSON.unsafe_load(StringIO.new(source)) object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
Ein File-Objekt laden
path = 't.json' File.write(path, source) File.open(path) do |file| JSON.unsafe_load(file) end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
Wenn proc gegeben ist
-
Modifiziert
sourcewie oben. -
Erhält das
resultdurch Aufruf vonparse(source, opts). -
Ruft
proc(result)rekursiv auf. -
Gibt das Endergebnis zurück.
Beispiel
require 'json' # Some classes for the example. class Base def initialize(attributes) @attributes = attributes end end class User < Base; end class Account < Base; end class Admin < Base; end # The JSON source. json = <<-EOF { "users": [ {"type": "User", "username": "jane", "email": "jane@example.com"}, {"type": "User", "username": "john", "email": "john@example.com"} ], "accounts": [ {"account": {"type": "Account", "paid": true, "account_id": "1234"}}, {"account": {"type": "Account", "paid": false, "account_id": "1235"}} ], "admins": {"type": "Admin", "password": "0wn3d"} } EOF # Deserializer method. def deserialize_obj(obj, safe_types = %w(User Account Admin)) type = obj.is_a?(Hash) && obj["type"] safe_types.include?(type) ? Object.const_get(type).new(obj) : obj end # Call to JSON.unsafe_load ruby = JSON.unsafe_load(json, proc {|obj| case obj when Hash obj.each {|k, v| obj[k] = deserialize_obj v } when Array obj.map! {|v| deserialize_obj v } end obj }) pp ruby
Ausgabe
{"users"=>
[#<User:0x00000000064c4c98
@attributes=
{"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
#<User:0x00000000064c4bd0
@attributes=
{"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
"accounts"=>
[{"account"=>
#<Account:0x00000000064c4928
@attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
{"account"=>
#<Account:0x00000000064c4680
@attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
"admins"=>
#<Admin:0x00000000064c41f8
@attributes={"type"=>"Admin", "password"=>"0wn3d"}>}