Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dump strings in YAML using literal scalar style?

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.

like image 267
mislav Avatar asked Mar 09 '12 20:03

mislav


People also ask

Does YAML support multiline string?

Multi-line blocks and long strings. YAML also supports writing strings on multiple lines in your YAML, with two different styles: literal and folded. Those are represented by a | (for literal style) or > (for folded style) header line (see examples below), and we will go into their differences soon.

What are scalars in YAML?

Scalars in YAML are written in block format using a literal type which is denoted as(|). It denotes line breaks count. In YAML, scalars are written in folded style (>) where each line denotes a folded space which ends with an empty line or more indented line.

How to make a new line in yml?

If you would like them to be kept as newlines, use the literal style, indicated by a pipe ( | ). If instead you want them to be replaced by spaces, use the folded style, indicated by a right angle bracket ( > ). (To get a newline using the folded style, leave a blank line by putting two newlines in.


1 Answers

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
}
like image 133
Aaron Patterson Avatar answered Nov 15 '22 02:11

Aaron Patterson