java - 在 SnakeYAML 中折叠单子(monad) bean

标签 java yaml snakeyaml

我有一个类型,它是 Map<String, Integer> 的简单包装器,我正在使用 SnakeYAML 将其转储到 YAML。

举个例子:

class Flags {
    private final Map<String, Boolean> _flags = new HashMap<>();
    Boolean get(String flag) {
        return _flags.containsKey(flag) ? _flags.get(flag) : false;
    }
    boolean put(String flag, Boolean value) {
        return _flags.put(flag, value);
    }
}

目前,我正在使用 DumperOptionsallowReadOnlyProperties = trueBeanAccessFIELD正确转储此类。当放入包含类时,我得到一个 dumpAsMap像这样的 YAML:

flags:
    _flags: {}

我想让 SnakeYAML 转储这个:

flags: {}

如何完成单元素层的扁平化?由于内部变量是私有(private)的,并且包装类型应该有效地充当包装类型,因此包装类型应该像包装类型一样被序列化是有意义的。

基本上,我希望包装类型被序列化就好像它是包装类型一样。现在没有也永远不会有其他变量需要序列化这个类在包装变量之外。我愿意更改包装类型的类型声明,但包装类型必须保留用于我的用例。

可运行复制案例的完整源代码:

import org.yaml.snakeyaml.*;
import org.yaml.snakeyaml.introspector.*;
import java.util.*;

public class Example {
    private final Flags flags = new Flags();
    public Flags getFlags() { return flags; }

    public static void main(String[] args) {
        DumperOptions options = new DumperOptions();
        options.setAllowReadOnlyProperties(true);
        Yaml yaml = new Yaml(options);
        yaml.setBeanAccess(BeanAccess.FIELD);
        System.out.println(yaml.dumpAsMap(new Example()));
    }
}

class Flags {
    private final Map<String, Boolean> _flags = new HashMap<>();
    Boolean get(String flag) {
        return _flags.containsKey(flag) ? _flags.get(flag) : false;
    }
    boolean put(String flag, Boolean value) {
        return _flags.put(flag, value);
    }
}

最佳答案

这样的事情可能有效(没有测试代码):

class FlagsRepresenter extends Representer {
    public FlagsRepresenter() {
        this.representers.put(Flags.class, new RepresentFlags());
    }

    private class RepresentFlags implements Represent {
        public Node representData(Object data) {
            // going the hacky, painful way of accessing a private field here.
            // YMMV.
            try {
                final Field f = data.getClass().getDeclaredField("_flags");
                f.setAccessible(true);
                final Map<String, Boolean> inner =
                        (Map<String, Boolean>) f.get(data);
                return representMapping(Tag.MAP, inner, null);
            } catch (final Exception ignored) {
                // will not occur as long as field _flags exists and has the
                // expected type.
                return null;
            }

        }
    }
}

像这样使用它:

Yaml yaml = new Yaml(new FlagsRepresenter(), new DumperOptions());

关于java - 在 SnakeYAML 中折叠单子(monad) bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40714518/

相关文章:

java 深入列出目录并进行操作

java - 如何使用 POI Excel 以编程方式拉伸(stretch)列以适合文本?

yaml - sphinx 配置 ||配置/sphinx.yml

json - 何时使用 YAML 而不是 JSON

ruby - 如何使用 Psych 在 YAML 文档中发出评论?

java - YAML 自定义对象

java - 为什么抽象变量 null 不等于 null

java - 保存到 mysql 数据库时出现 jbutton 问题

java - 如何使用 snakeYAML 加载 java.util.Set

java - 如何从java中的YAML文件中读取?