简体   繁体   中英

Write a literal YAML field using Groovy 3.0's new YamlBuilder

Groovy 3.0 has a new YamlBuilder class that works in a similar way to the existing JsonBuilder class.

I'm trying to work out if I can use YamlBuilder to generate a literal field in YAML such as:

data: |
  this is
  a literal
  text value

My first guess was Groovy's multiline string would work:

new YamlBuilder() {
  data: '''\
this is
a literal
text value'''
}

But that gives me:

data: "this is\na literal\ntext value\n"`

I don't see anything useful in the YamlBuilder Javadoc and mrhaki's example doesn't show this use-case.

Does anyone know if/how this can be done?

You can do the following:

import groovy.yaml.*
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import static com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature.LITERAL_BLOCK_STYLE

def yaml = new YamlBuilder()

yaml {
  data '''\
this is
a literal
text value'''
}

println new ObjectMapper(new YAMLFactory().configure(LITERAL_BLOCK_STYLE, true)).writeValueAsString(yaml)

If you need your own custom serialization

Under the covers Groovy's YamlBuilder is using Jackson's JSON to YAML converter.

Jackson's converter does support literal block style, but this needs to be enabled. The current version of YamlBuilder does not support setting options.

I copied the YamlBuilder class and the related YamlConverter class so I could modify the settings.

In the YamlBuilder class, I modified this method:

public static String convertJsonToYaml(Reader jsonReader) {
    try (Reader reader = jsonReader) {
        JsonNode json = new ObjectMapper().readTree(reader);

        return new YAMLMapper().writeValueAsString(json);
    } catch (IOException e) {
        throw new YamlRuntimeException(e);
    }
}

To be this:

public static String convertJsonToYaml(Reader jsonReader) {
    try (Reader reader = jsonReader) {
        JsonNode json = new ObjectMapper().readTree(reader);

        YAMLMapper mapper = new YAMLMapper()
        mapper.configure(YAMLGenerator.Feature.LITERAL_BLOCK_STYLE, true)
        return mapper.writeValueAsString(json);
    } catch (IOException e) {
        throw new YamlRuntimeException(e);
    }
}

This allows me to do:

mapper.configure(YAMLGenerator.Feature.LITERAL_BLOCK_STYLE, true)

Which will successfully render the YAML as a literal block:

data: |-
  this is
  a literal
  text value

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM