您好,登錄后才能下訂單哦!
今天小編給大家分享一下Ruby怎么解析處理YAML和json格式數據的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
Ruby的標準庫YAML基于Psych
require 'yaml'
之后,為大多數的基本數據類型都提供了 to_ yaml()
方法,用于將各數據類型的對象轉換為yaml格式。
例如:
require 'yaml' require 'set' p "hello world".to_yaml p 123.to_yaml p %w(perl shell php).to_yaml p ({one: 1, two: 2}).to_yaml p Set.new([1,2,3]).to_yaml
得到:
"--- hello world\n" "--- 123\n" "---\n- perl\n- shell\n- php\n" "---\n:one: 1\n:two: 2\n" "--- !ruby/object:Set\nhash:\n 1: true\n 2: true\n 3: true\n"
也可以使用YAML.dump()
方法實現和to_yaml相同的功能,它還可以寫入文件。
users = [{name: 'Bob', permissions: ['Read']}, {name: 'Alice', permissions:['Read', 'Write']}] File.open("/tmp/a.yml","w") { |f| YAML.dump(users, f) }
查看文件:
--- - :name: Bob #=> 注意,保留了hash源數據中的符號 :permissions: - Read - :name: Alice :permissions: - Read - Write
用YAML.load()從YAML中讀取數據:
require 'yaml' pp YAML.load(DATA) __END__ mysql: passwd: P@ssword1! user: root port: 3306 other1: nil other2: false other3: "" hosts: - ip: 10.10.1.1 hostname: node1 - ip: 10.10.1.2 hostname: node2
得到:
{"mysql"=> {"passwd"=>"P@ssword1!", #=> 注意,key是String而非Symbol "user"=>"root", "port"=>3306, "other1"=>"nil", "other2"=>false, "other3"=>"", "hosts"=> [{"ip"=>"10.10.1.1", "hostname"=>"node1"}, {"ip"=>"10.10.1.2", "hostname"=>"node2"}]}}
如果想讓hash的key是符號而非字符串,可以設置選項symbolize_names: true
:
pp YAML.load(DATA, symbolize_names: true)
需要注意,YAML可以將對象進行序列化,所以有幾方面注意事項:
在反序列化的時候需要也require涉及到的文件,例如對Set類型序列化后,在反序列化時如不require 'set'
則無法還原對象
有些底層對象不能序列化,包括IO流、Ruby代碼對象Proc、Binding等
不要反序列化不被信任的數據對象(比如用戶輸入的數據),此時可使用safe_load(),它默認只允許加載以下幾種類型的數據:
TrueClass
FalseClass
NilClass
Numeric
String
Array
Hash
如果確實想要加載額外的數據類型,可以在safe_load()中指定參數permitted_classes: []或permitted_symbols: []
使用JSON.generate()可以將對象或數組轉換為JSON格式的數據:
require 'json' p JSON.generate "abc" p JSON.generate 123 p JSON.generate true p JSON.generate nil p JSON.generate [2,3,4] p JSON.generate({name: "junmajinlong", age: 23}) require 'set' p JSON.generate(Set.new([1,23,44]))
得到:
"\"abc\"" "123" "true" "null" "[2,3,4]" "{\"name\":\"junmajinlong\",\"age\":23}" "\"#<Set: {1, 23, 44}>\""
當require 'json'
后,很多ruby類型都具備了一個to_json的方法,可以直接將該類型的數據轉換為json數據:
p ({name: "junmajinlong", age: 23}).to_json p (Set.new([1,23,44])).to_json
得到:
"{\"name\":\"junmajinlong\",\"age\":23}" "\"#<Set: {1, 23, 44}>\""
此外,JSON.dump()也可以將對象轉換為JSON格式的字符串,而且它還支持寫入文件:
hsh = {name: "junmajinlong", age: 23} File.open("/tmp/a.json", "w") {|f| JSON.dump(hsh, f)}
要從json格式字符串轉為ruby對象,有一些選項可設置,比如*symbolize_names*
選項表示是否將json object中的key解析為符號類型的key,如果設置為false,則解析為字符串的key。
要將json格式的字符串解析為Ruby數據類型(Hash),使用JSON.parse()
,
require 'json' hsh = '{"name": "junmajinlong", "age": 23}' p JSON.parse(hsh) p JSON.parse(hsh, symbolize_names: true)
注意,上面的json字符串必須是合理的json數據,比如key必須使用雙引號包圍而不能使用單引號,字符串必須使用雙引號包圍,等等。比如"{'name': 'junmajinlong', 'age': 23}"
就不是合理的json字符串。
要從json文件中讀取json數據并轉換為Ruby數據,使用load():
data = File.open("/tmp/a.json") do |f| JSON.load(f) end pp data #=> {"name"=>"junmajinlong", "age"=>23}
json支持的數據類型有:
字符串
數值
對象
數組
布爾
Null
從一種語言的數據轉換為Json數據時,如果數據類型也是JSON所支持的,可直接轉換,但如果包含了JSON不支持的類型,則可能報錯,也可能以一種對象字符串的方式保存,這取決于對應的實現。
可以在對象中定義as_json
實例方法來決定對象如何轉換為json字符串,再定義類方法from_json()
來決定如何從json字符串中恢復為一個對象。
例如,
require 'json' require 'date' class Person attr_accessor :name, :birthday def initialize name, birthday @name = name @birthday = DateTime.parse(birthday) end end File.open("/tmp/p.json", "w") do |f| JSON.dump(Person.new("junmajinlong", "1999-10-11"), f) end
查看保存的json數據:
$ cat /tmp/p.json "#<Person:0x00007fffc7e575d0>"
定義as_json
和frmo_json
:
require 'json' require 'date' class Person attr_accessor :name, :birthday def initialize name, birthday @name = name @birthday = DateTime.parse(birthday) end def as_json { name: @name, birthday: @birthday.strftime("%F") } end def self.from_json json data = JSON.parse(json) new(data["name"], data["birthday"]) end end
之后要序列化、反序列化該對象,可:
data = Person.new("junmajinlong", "1999-10-11").as_json p data p1=Person.from_json(JSON.dump data) p p1.birthday
如果是讀寫json文件,可:
person1 = Person.new("junmajinlong", "1999-10-11") File.open("/tmp/p.json", "w") do |f| JSON.dump(person1.as_json, f) end p1 = File.open("/tmp/p.json") do |f| Person.from_json(f.read) # Person.from_json(JSON.load(f).to_json) end p p1
測試了json標準庫、oj和fast_josnparser解析json的性能,測試項包括:
從文件中加載并解析json字符串為ruby對象
從內存json字符串中解析json字符串為ruby對象
帶有symbolize_keys/symbolize_names轉換時的解析
json標準庫和oj將ruby對象dump為json字符串
json標準庫和oj將ruby對象dump為json字符串保存到文件
注:
fast_jsonparser沒有dump功能,只有解析json字符串功能
oj在將對象轉換為json字符串時,可能會丟失數據的精度,比如浮點數的精度
測試的json字符串數量大約50M。
測試了ruby 2.7.1和ruby 3.0.1兩個版本,gem包的版本信息如下:
fast_jsonparser (0.5.0) json (default: 2.5.1) oj (3.11.7)
測試代碼:
require 'benchmark' require 'json' require 'oj' require 'fast_jsonparser' # warm json_file='test' # 文件大小大約50M str = File.read(json_file) ######## JSON puts " load file ".center(80, '-') Benchmark.bm(30) do |x| x.report("JSON.load:") { File.open(json_file){ |f| JSON.load(f) } } x.report("Oj.load_file:") { Oj.load_file(json_file) } x.report("FastJsonparser.load:") { FastJsonparser.load(json_file) } end puts puts " load file with symbolize_keys ".center(80, '-') Benchmark.bm(30) do |x| x.report("JSON.load:") { File.open(json_file){ |f| JSON.load(f, nil, symbolize_names: true, create_additions: false) } } x.report("Oj.load_file:") { Oj.load_file(json_file, symbol_keys: true) } x.report("FastJsonparser.load:") { FastJsonparser.load(json_file, symbolize_keys: true) } end puts puts " parse str ".center(80, '-') Benchmark.bm(30) do |x| x.report("JSON.parse:") { JSON.parse(str) } x.report("Oj.load:") { Oj.load(str) } x.report("FastJsonparser.parse:") { FastJsonparser.parse(str) } end puts puts " parse str with symbolize_keys ".center(80, '-') Benchmark.bm(30) do |x| x.report("JSON.parse:") { JSON.parse(str, symbolize_names: true) } x.report("Oj.load:") { Oj.load(str, symbol_keys: true) } x.report("FastJsonparser.parse:") { FastJsonparser.parse(str, symbolize_keys: true) } end obj = JSON.parse(str, symbolize_names: true) puts puts " dump JSON to str ".center(80, '-') Benchmark.bm(30) do |x| x.report("JSON.dump:") { JSON.dump(obj) } x.report("Oj.dump:") { Oj.dump(obj) } end puts puts " dump JSON to file ".center(80, '-') Benchmark.bm(30) do |x| x.report("JSON.dump:") { File.open('0_json_dump', 'w') {|f| JSON.dump(obj, f) } } x.report("Oj.to_file:") { Oj.to_file('0_oj_dump', obj) } end
測試結果:
Ruby 2.7.1中:
---------------------------------- load file ----------------------------------- user system total real JSON.load: 1.591831 0.058021 1.649852 ( 1.738119) Oj.load_file: 1.350385 0.057684 1.408069 ( 2.434268) <-慢 FastJsonparser.load: 0.653968 0.103258 0.757226 ( 0.848913) <-快 ------------------------ load file with symbolize_keys ------------------------- user system total real JSON.load: 1.212617 0.039052 1.251669 ( 1.349545) Oj.load_file: 1.432059 0.098950 1.531009 ( 2.679610) <-慢 FastJsonparser.load: 0.695538 0.008384 0.703922 ( 0.797081) <-快 ---------------------------------- parse str ----------------------------------- user system total real JSON.parse: 1.343596 0.000000 1.343596 ( 1.350368) Oj.load: 1.133612 0.000000 1.133612 ( 1.140939) FastJsonparser.parse: 0.701701 0.012340 0.714041 ( 0.720296) <-快 ------------------------ parse str with symbolize_keys ------------------------- user system total real JSON.parse: 1.250775 0.000000 1.250775 ( 1.258796) Oj.load: 1.131296 0.000000 1.131296 ( 1.138020) FastJsonparser.parse: 0.697433 0.015962 0.713395 ( 0.719439) <-快 ------------------------------- dump JSON to str ------------------------------- user system total real JSON.dump: 1.374611 0.028454 1.403065 ( 1.403081) Oj.dump: 1.025049 0.040184 1.065233 ( 1.065246) <-快 ------------------------------ dump JSON to file ------------------------------- user system total real JSON.dump: 1.234362 0.040246 1.274608 ( 1.369214) Oj.to_file: 1.168707 0.000000 1.168707 ( 1.270957)
Ruby 3.0.1中:
---------------------------------- load file ----------------------------------- user system total real JSON.load: 1.362151 0.083610 1.445761 ( 1.569754) Oj.load_file: 1.343601 0.182046 1.525647 ( 2.684472) <-慢 FastJsonparser.load: 2.634435 0.052734 2.687169 ( 2.776105) <-慢 ------------------------ load file with symbolize_keys ------------------------- user system total real JSON.load: 1.287954 0.018572 1.306526 ( 1.409770) Oj.load_file: 1.478750 0.043847 1.522597 ( 2.668882) <-慢 FastJsonparser.load: 2.717857 0.006164 2.724021 ( 2.822728) <-慢 ---------------------------------- parse str ----------------------------------- user system total real JSON.parse: 1.242225 0.008661 1.250886 ( 1.304554) Oj.load: 1.097922 0.000000 1.097922 ( 1.110031) FastJsonparser.parse: 2.602679 0.017232 2.619911 ( 2.634604) <-慢 ------------------------ parse str with symbolize_keys ------------------------- user system total real JSON.parse: 1.368262 0.000000 1.368262 ( 1.380730) Oj.load: 1.332349 0.000000 1.332349 ( 1.346331) FastJsonparser.parse: 2.706804 0.007238 2.714042 ( 2.726935) <-慢 ------------------------------- dump JSON to str ------------------------------- user system total real JSON.dump: 1.724653 0.009250 1.733903 ( 1.733912) Oj.dump: 1.298235 0.030041 1.328276 ( 1.328279) <-快 ------------------------------ dump JSON to file ------------------------------- user system total real JSON.dump: 1.765664 0.040595 1.806259 ( 1.905785) Oj.to_file: 1.228744 0.020309 1.249053 ( 1.349684) <-快 =end
性能測試結論:
(1).ruby 3之前,fast_jsonparser非常快,但是Ruby 3中的fast_jsonparser很慢
(2).OJ解析本地json字符串的性能比標準庫json性能稍好,但oj從文件中加載并解析json的速度很慢
(3).OJ將ruby對象解析為json字符串的效率比json標準庫性能好
即:
dump: Oj.dump > JSON.dump ruby3 之前: FastJsonparser.load > JSON.load > Oj.load_file FastJsonparser.parse > Oj.load > JSON.parse ruby3 之后: JSON.load > Oj.load_file > FastJsonparser.load Oj.load > JSON.parse > FastJsonparser.parse
有一個名為multi_json的gem包,它提供多種json包的功能,默認采用OJ作為json的適配引擎。它支持下面幾種json適配器:
Oj Optimized JSON by Peter Ohler
Yajl Yet Another JSON Library by Brian Lopez
JSON The default JSON gem with C-extensions (ships with Ruby 1.9+)
JSON Pure A Ruby variant of the JSON gem
NSJSONSerialization Wrapper for Apple’s NSJSONSerialization in the Cocoa Framework (MacRuby only)
gson.rb A Ruby wrapper for google-gson library (JRuby only)
JrJackson JRuby wrapper for Jackson (JRuby only)
OkJson A simple, vendorable JSON parser
如果oj已被require,則默認采用oj處理json,如果oj沒有被require,而是require了yajl,則采用yajl處理json,依次類推。
它提供了load()和dump()方法:
load(json_str, options = {}) options: symbolize_keys: true, false adapter: oj, json_gem, yajl, json_pure, ok_json dump(object, options = {})
以上就是“Ruby怎么解析處理YAML和json格式數據”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。