本文簡要介紹ruby語言中 JSON模塊
的用法。
JavaScript 對象表示法 (JSON)
JSON 是一種輕量級的數據交換格式。
JSON 值是以下之一:
-
雙引號文本:
"foo"
。 -
編號:
1
、1.0
、2.0e2
。 -
布爾值:
true
、false
。 -
空:
null
。 -
數組:值的有序列表,用方括號括起來:
["foo", 1, 1.0, 2.0e2, true, false, null]
-
對象:名稱/值對的集合,用花括號括起來;每個名稱都是雙引號文本;這些值可以是任何 JSON 值:
{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}
JSON 數組或對象可以包含任何深度的嵌套數組、對象和標量:
{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}
[{"foo": 0, "bar": 1}, ["baz", 2]]
使用模塊 JSON
要使模塊 JSON 在您的代碼中可用,請從以下內容開始:
require 'json'
這裏的所有示例都假設這已經完成。
解析 JSON
您可以使用以下兩種方法之一解析包含 JSON 數據的字符串:
-
JSON.parse(source, opts)
-
JSON.parse!(source, opts)
其中
-
source
是一個 Ruby 對象。 -
opts
是一個 Hash 對象,其中包含控製輸入允許和輸出格式的選項。
兩種方法的區別在於 JSON.parse!
省略了一些檢查,對於一些source
數據可能不安全;僅將其用於來自受信任來源的數據。對於不太受信任的來源,請使用更安全的方法 JSON.parse
。
解析 JSON 數組
當source
是 JSON 數組時, JSON.parse
默認返回 Ruby 數組:
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
JSON 數組可以包含任意深度的嵌套數組、對象和標量:
json = '[{"foo": 0, "bar": 1}, ["baz", 2]]'
JSON.parse(json) # => [{"foo"=>0, "bar"=>1}, ["baz", 2]]
解析 JSON 對象
當源是 JSON 對象時, JSON.parse
默認返回一個 Ruby 哈希:
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
JSON 對象可以包含任何深度的嵌套數組、對象和標量:
json = '{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}'
JSON.parse(json) # => {"foo"=>{"bar"=>1, "baz"=>2}, "bat"=>[0, 1, 2]}
解析 JSON 標量
當源是 JSON 標量(不是數組或對象)時, JSON.parse
返回 Ruby 標量。
String :
ruby = JSON.parse('"foo"')
ruby # => 'foo'
ruby.class # => String
整數:
ruby = JSON.parse('1')
ruby # => 1
ruby.class # => Integer
浮點數:
ruby = JSON.parse('1.0')
ruby # => 1.0
ruby.class # => Float
ruby = JSON.parse('2.0e2')
ruby # => 200
ruby.class # => Float
布爾值:
ruby = JSON.parse('true')
ruby # => true
ruby.class # => TrueClass
ruby = JSON.parse('false')
ruby # => false
ruby.class # => FalseClass
空值:
ruby = JSON.parse('null')
ruby # => nil
ruby.class # => NilClass
解析選項
選項max_nesting
(整數)指定允許的最大嵌套深度;默認為 100
;指定 false
以禁用深度檢查。
使用默認值 false
:
source = '[0, [1, [2, [3]]]]'
ruby = JSON.parse(source)
ruby # => [0, [1, [2, [3]]]]
太深:
# Raises JSON::NestingError (nesting of 2 is too deep):
JSON.parse(source, {max_nesting: 1})
壞值:
# Raises TypeError (wrong argument type Symbol (expected Fixnum)):
JSON.parse(source, {max_nesting: :foo})
選項 allow_nan
(boolean) 指定是否在 source
中允許 NaN
、 Infinity
和 MinusInfinity
;默認為 false
。
使用默認值 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]')
允許:
source = '[NaN, Infinity, -Infinity]'
ruby = JSON.parse(source, {allow_nan: true})
ruby # => [NaN, Infinity, -Infinity]
Option symbolize_names
(boolean) 指定返回的Hash鍵是否應該是Symbols;默認為false
(使用字符串)。
使用默認值 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}
使用符號:
ruby = JSON.parse(source, {symbolize_names: true})
ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
選項object_class
(Class) 指定要用於每個 JSON 對象的 Ruby 類;默認為哈希。
默認情況下,哈希:
source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
ruby = JSON.parse(source)
ruby.class # => Hash
使用類 OpenStruct:
ruby = JSON.parse(source, {object_class: OpenStruct})
ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
選項 array_class
(Class) 指定要用於每個 JSON 數組的 Ruby 類;默認為數組。
默認情況下,數組:
source = '["foo", 1.0, true, false, null]'
ruby = JSON.parse(source)
ruby.class # => Array
使用類集:
ruby = JSON.parse(source, {array_class: Set})
ruby # => #<Set: {"foo", 1.0, true, false, nil}>
選項create_additions
(布爾值)指定是否在解析中使用 JSON 添加。請參閱 JSON 添加。
生成 JSON
要生成包含 JSON 數據的 Ruby 字符串,請使用方法 JSON.generate(source, opts)
,其中
-
source
是一個 Ruby 對象。 -
opts
是一個 Hash 對象,其中包含控製輸入允許和輸出格式的選項。
從數組生成 JSON
當源是 Ruby 數組時, JSON.generate
返回一個包含 JSON 數組的字符串:
ruby = [0, 's', :foo]
json = JSON.generate(ruby)
json # => '[0,"s","foo"]'
Ruby Array 數組可以包含任意深度的嵌套數組、散列和標量:
ruby = [0, [1, 2], {foo: 3, bar: 4}]
json = JSON.generate(ruby)
json # => '[0,[1,2],{"foo":3,"bar":4}]'
從哈希生成 JSON
當源是 Ruby 哈希時, JSON.generate
返回一個包含 JSON 對象的字符串:
ruby = {foo: 0, bar: 's', baz: :bat}
json = JSON.generate(ruby)
json # => '{"foo":0,"bar":"s","baz":"bat"}'
Ruby 哈希數組可以包含任何深度的嵌套數組、哈希和標量:
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
當源既不是 Array 也不是 Hash 時,生成的 JSON 數據取決於源的類。
當源是 Ruby Integer 或 Float 時, JSON.generate
返回一個包含 JSON 數字的字符串:
JSON.generate(42) # => '42'
JSON.generate(0.42) # => '0.42'
當源是 Ruby 字符串時, JSON.generate
返回一個包含 JSON 字符串的字符串(使用 double-quotes):
JSON.generate('A string') # => '"A string"'
當源為 true
、 false
或 nil
時, JSON.generate
返回一個包含相應 JSON 令牌的字符串:
JSON.generate(true) # => 'true'
JSON.generate(false) # => 'false'
JSON.generate(nil) # => 'null'
當源不是上述情況時, JSON.generate
返回一個包含源的 JSON 字符串表示形式的字符串:
JSON.generate(:foo) # => '"foo"'
JSON.generate(Complex(0, 0)) # => '"0+0i"'
JSON.generate(Dir.new('.')) # => '"#<Dir>"'
生成選項
選項allow_nan
(布爾值)指定是否可以生成NaN
、Infinity
和-Infinity
;默認為 false
。
使用默認值 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)
允許:
ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity]
JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
選項 max_nesting
(Integer) 指定 obj
中的最大嵌套深度;默認為 100
。
使用默認值 100
:
obj = [[[[[[0]]]]]]
JSON.generate(obj) # => '[[[[[[0]]]]]]'
太深:
# Raises JSON::NestingError (nesting of 2 is too deep):
JSON.generate(obj, max_nesting: 2)
默認格式選項生成最緊湊的 JSON 數據,全部在一行上,沒有空格。
您可以使用這些格式化選項使用空格以更開放的格式生成 JSON 數據。另見 JSON.pretty_generate
。
-
選項
array_nl
(String) 指定要在每個 JSON 數組之後插入的字符串(通常是換行符);默認為空字符串''
。 -
選項
object_nl
(String) 指定要在每個 JSON 對象之後插入的字符串(通常是換行符);默認為空字符串''
。 -
Option
indent
(String) 指定用於縮進的字符串(通常是空格);默認為空字符串,''
;默認為空字符串,''
;除非選項array_nl
或object_nl
指定換行符,否則無效。 -
選項
space
(String) 指定要在每個 JSON 對象對中的冒號之後插入的字符串(通常是空格);默認為空字符串''
。 -
選項
space_before
(String) 指定要在每個 JSON 對象對中的冒號之前插入的字符串(通常是空格);默認為空字符串''
。
在此示例中,首先使用 obj
生成最短的 JSON 數據(無空格),然後再次使用指定的所有格式選項:
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)
輸出:
Compact: {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}} Open: { "foo" : [ "bar", "baz" ], "bat" : { "bam" : 0, "bad" : 1 } }
JSON 添加
當你“round trip”一個非字符串對象從 Ruby 到 JSON 並返回時,你有一個新的字符串,而不是你開始的對象:
ruby0 = Range.new(0, 2)
json = JSON.generate(ruby0)
json # => '0..2"'
ruby1 = JSON.parse(json)
ruby1 # => '0..2'
ruby1.class # => String
您可以使用 JSON additions
來保留原始對象。添加是 ruby 類的擴展,因此:
-
JSON.generate 在 JSON 字符串中存儲更多信息。
-
JSON.parse 使用選項
create_additions
調用,使用該信息創建適當的 Ruby 對象。
此示例顯示一個 Range 被生成為 JSON 並被解析回 Ruby,無論是否添加 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
此輸出顯示不同的結果:
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)
JSON 模塊包含某些類的附加內容。您還可以製作自定義添加項。請參閱自定義 JSON 添加。
內置添加
JSON 模塊包括對某些類的添加。要使用加法,require
它的來源:
-
大十進製:
require 'json/add/bigdecimal'
-
複雜:
require 'json/add/complex'
-
日期:
require 'json/add/date'
-
日期時間:
require 'json/add/date_time'
-
異常:
require 'json/add/exception'
-
開放結構:
require 'json/add/ostruct'
-
範圍:
require 'json/add/range'
-
理性:
require 'json/add/rational'
-
正則表達式:
require 'json/add/regexp'
-
設置:
require 'json/add/set'
-
結構:
require 'json/add/struct'
-
符號:
require 'json/add/symbol'
-
時間:
require 'json/add/time'
為了減少標點混亂,下麵的示例顯示了通過 puts
而不是通常的 inspect
生成的 JSON,
大十進製:
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
複雜的:
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
日期:
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
約會時間:
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
異常(及其子類,包括 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
開放結構:
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
範圍:
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
合理的:
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
正則表達式:
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
放:
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
結構:
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
象征:
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
時間:
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
自定義 JSON 添加
除了提供的 JSON 添加之外,您還可以為 Ruby 內置類或用戶定義的類製作自己的 JSON 添加。
這是一個用戶定義的類 Foo
:
class Foo
attr_accessor :bar, :baz
def initialize(bar, baz)
self.bar = bar
self.baz = baz
end
end
這是它的 JSON 添加:
# 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
示範:
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
輸出:
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)
相關用法
- Ruby JSON.generator用法及代碼示例
- Ruby JSON.load_file!用法及代碼示例
- Ruby JSON.dump_default_options用法及代碼示例
- Ruby JSON.generate用法及代碼示例
- Ruby JSON.load用法及代碼示例
- Ruby JSON.state用法及代碼示例
- Ruby JSON.load_default_options用法及代碼示例
- Ruby JSON.load_file用法及代碼示例
- Ruby JSON.pretty_generate用法及代碼示例
- Ruby JSON.dump用法及代碼示例
- Ruby JSON.parse用法及代碼示例
- Ruby JSON.fast_generate用法及代碼示例
- Ruby JSON[object]用法及代碼示例
- Ruby JSON.parse!用法及代碼示例
- Ruby JSON.parser用法及代碼示例
- Ruby JSON.create_id=用法及代碼示例
- Ruby Time tv_sec用法及代碼示例
- Ruby MatchData.pre_match用法及代碼示例
- Ruby Symbol capitalize用法及代碼示例
- Ruby Matrix lup()用法及代碼示例
- Ruby SizedQueue clear()用法及代碼示例
- Ruby Object.instance_variable_get用法及代碼示例
- Ruby Spotter.spot_op_asgn2_for_name用法及代碼示例
- Ruby Float arg()用法及代碼示例
- Ruby WIN32OLE_METHOD#visible?用法及代碼示例
注:本文由純淨天空篩選整理自ruby-lang.org大神的英文原創作品 JSON模塊。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。