How to dump strings in YAML using literal scalar style?
Asked Answered
C

1

7

I have a big string of formatted data (e.g. JSON) that I want to dump to YAML using Psych in ruby while preserving formatting.

Basically, I want for JSON to appear in YAML using literal style:

---
json: |
  {
    "page": 1,
    "results": [
      "item", "another"
    ],
    "total_pages": 0
  }

However, when I use YAML.dump it doesn't use literal style. I get something like this:

---
json: ! "{\n  \"page\": 1,\n  \"results\": [\n    \"item\", \"another\"\n  ],\n  \"total_pages\":
  0\n}\n"

How can I tell Psych to dump scalars in wanted style?


Solution:

Big thanks to Aaron Patterson for his solution that I'm expanding on here: https://gist.github.com/2023978

Although a bit verbose, that gist is a working way of tagging certain strings in ruby to be output using literal style in YAML.

Corr answered 9/3, 2012 at 20:7 Comment(1)
Related: #4605306Corr
L
11
require 'psych'

# Construct an AST
visitor = Psych::Visitors::YAMLTree.new({})
visitor << DATA.read
ast = visitor.tree

# Find all scalars and modify their formatting
ast.grep(Psych::Nodes::Scalar).each do |node|
  node.plain  = false
  node.quoted = true
  node.style  = Psych::Nodes::Scalar::LITERAL
end

begin
  # Call the `yaml` method on the ast to convert to yaml
  puts ast.yaml
rescue
  # The `yaml` method was introduced in later versions, so fall back to
  # constructing a visitor
  Psych::Visitors::Emitter.new($stdout).accept ast
end

__END__
{
  "page": 1,
  "results": [
    "item", "another"
],
  "total_pages": 0
}
Lyrate answered 12/3, 2012 at 16:20 Comment(1)
Thanks, Aaron! Your code, however, is a tad destructive since it walks through all scalars in the tree (keys, numbers, everything) and marks them for output using literal style, which messes up the rest of the YAML document. Inspired by your code, I've updated the question above with my own take which eliminates the step in which you walk the tree.Corr

© 2022 - 2024 — McMap. All rights reserved.