Psych YAML parsing including comments
Asked Answered
W

3

14

According to http://yaml.org/spec/current.html#id2509980 comments in YAML files are a presentational detail and must not be in the serialization/representation graph ( http://yaml.org/spec/current.html#representation/). It looks like Psych is parsing according to spec and loses the comments which means that it is not possible to parse a YAML file and serialize it again exactly the same way when the file contains comments. Which in my opinion is very strange because comments do matter in such file (e.g. configs).

Does anyone know if it possible to parse comments with an existing library or is the only way to go to do it all by myself?

Woodcutter answered 31/7, 2012 at 6:52 Comment(2)
It's a stretch, but you could clone it into a temporary file before loading it in and then merge the two files after serialization (using diff?)... as long as the overall structure was the same... or... is that kind of a crazy idea...?Bankbook
This blog post suggests the only comment-preserving YAML parser is ruamel, which is for Python.Haya
M
2

We can do some thing like this also, which would change the key value and also keep the comments.

require 'yaml'
thing = YAML.load_file('/opt/database.yml')
hostname = thing["common"]["host_name"]
appname = thing["common"]["app_name"]
motdobj = IO.readlines('/opt/database.yml')
motdobj = motdobj.map {|s| s.gsub(hostname, "mrigesh")}
motdobj = motdobj.map {|s| s.gsub(appname, "abc")}

File.open('/opt/database.yml', "w" ) do | file1 |
    file1.puts motdobj
    file1.close
end
Mckibben answered 28/10, 2014 at 10:48 Comment(0)
F
1

You could iterate over the nodes on a lower level keeping the comments when emitting. Also, you could see if syck engine gives you the result you are looking for.

Fibroid answered 10/5, 2013 at 2:19 Comment(2)
Related #16390830Fibroid
Related #14150070Fibroid
G
0

I liked @josh-voigts crazy idea. Here's a crazy implementation. Comments can be interspersed almost anywhere and it works!

require 'tempfile'

def yaml_conf_edit(fn, &block)
  conf = File.open(fn) {|f| YAML.load(f.read)}

  before = Tempfile.new('before')
  before.write(conf.to_yaml)
  before.close

  yield conf

  after = Tempfile.new('after')
  after.write(conf.to_yaml)
  after.close

  `merge #{fn} #{before.path} #{after.path}`
  before.unlink; after.unlink

  conf
end

Which you can use in something like:

yaml_conf_edit('conf/database.yml') do |conf| 
  conf['development']['database'] = db_timestamped
end
Gallopade answered 27/6, 2013 at 23:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.