Feature #12960
closed[psych] new visitor class to generate custom object instead of Hash
Description
I create a patch to define new useful visitor class for Psych.
It generates custom object as mapping data instead of Hash.
Normally, you must access YAML document data like ydoc["foo"]["bar"]["baz"].
Using this class, you can access data like ydoc.foo.bar.baz.
Example1: create custom object instead of Hash according to context
## define custom classes
Team = Struct.new('Team', 'name', 'members')
Member = Struct.new('Member', 'name', 'gender')
## create visitor object
require 'psych'
require 'psych/visitors/custom_class'
classmap = {
"teams" => Team,
"members" => Member,
}
visitor = Psych::Visitors::CustomClassVisitor.create(classmap)
## example YAML string
input = <<-'END'
teams:
- name: SOS Brigade
members:
- {name: Haruhi, gender: F}
- {name: Kyon, gender: M}
- {name: Mikuru, gender: F}
- {name: Itsuki, gender: M}
- {name: Yuki, gender: F}
END
## parse YAML string with creating Team or Member objects according to context
tree = Psych.parse(input)
ydoc = visitor.accept(tree)
p ydoc['teams'][0].class #=> Struct::Team
p ydoc['teams'][0]['members'][0].class #=> Struct::Member
team = ydoc['teams'][0]
p team.name #=> "SOS Brigade"
p team.members[0].name #=> "Haruhi"
p team.members[0].gender #=> "F"
Example2: create custom hash object
## allows `hash.foo` instead of `hash["foo"]`
class MagicHash < Hash
def method_missing(method, *args)
return super unless args.empty?
return self[method.to_s]
end
end
## create visitor with MagicHash
require 'psych'
require 'psych/visitors/custom_class'
classmap = {'*' => MagicHash} # '*' means default class
visitor = Psych::Visitors::CustomClassVisitor.create(classmap)
## example YAML document
input = <<-'END'
teams:
- name: SOS Brigade
members:
- {name: Haruhi, gender: F}
- {name: Kyon, gender: M}
- {name: Mikuru, gender: F}
- {name: Itsuki, gender: M}
- {name: Yuki, gender: F}
END
## parse YAML string with creating custom hash object instead of Hash
tree = Psych.parse(input)
ydoc = visitor.accept(tree)
p ydoc.class #=> MagicHash
p ydoc['teams'][0].class #=> MagicHash
p ydoc['teams'][0]['members'][0].class #=> MagicHash
p ydoc.teams[0].members[0].name #=> "Haruhi"
p ydoc.teams[0].members[0].gender #=> "F"
I believe this class is very useful, and hope it to be imported into ruby repository.
Let me know your opinion or impression.
Files
Updated by nobu (Nobuyoshi Nakada) almost 10 years ago
- Status changed from Open to Third Party's Issue
Please send to the upstream.
Updated by kwatch (makoto kuwata) almost 10 years ago
Nobuyoshi Nakada wrote:
Please send to the upstream.
I understand. Thx.
(I can't find any button to close this issue. Please close this.)
Updated by duerst (Martin Dürst) almost 10 years ago
makoto kuwata wrote:
(I can't find any button to close this issue. Please close this.)
The status is already "Third Party's Issue". You can think about this as a subcategory of "Closed".