根据其 java 等效项 class (SnakeYaml) 对 YAML 文件条目进行排序

Order YAML file entries according to its java equivalent class (SnakeYaml)

我正在对 Java 中的两个 load/dump 数据使用 SnakeYaml。为此,我创建了一个带有字段的自定义 class,假设 class 看起来像这样:

public class Person {
        private String name;
        private String lastName;
        private String address;
        
        public Person() {
            // Do nothing
        }
        
        // Getters and setters initialized for all the fields
    }

现在,我想要的是,当我使用 SnakeYaml 将 Person 对象写入文件时,我希望字段按照它们在 class.

中定义的顺序排列

例如

name: Patrick
lastName: Star
Age : 42

问题是,对于更高级的示例,此排序是实现的。目前我 writing/dumping 像下面这样的 yaml 文件:

Constructor struct = new Constructor(YamlIteratorModel.class);
Yaml yaml = new Yaml(struct);

try {
   String path = "Some/File/Path/yamlfile.yaml";
   FileWriter writer = new FileWriter(path);
   yaml.dump(iteratorModel, writer);
} catch (IOExcepton e) {
   // Do something
}

我还尝试过创建一个 Representer class 来扩展 Representer 并以类似的方式调用 Yaml 构造函数。这个取自另一个 post,它对我不起作用,因为它只按照我不完全确定的顺序对属性进行排序(现在找不到 link但如果我再次找到它会更新)..

public class ConfigurationModelRepresenter extends Representer {

    /**
     * Create object without specified dumper object
     */
    public ConfigurationModelRepresenter() {
        super();
    }

    /**
     * Create object with dumper options
     *
     * @param options
     */
    public ConfigurationModelRepresenter(DumperOptions options) {
        super(options);
    }

    /** {@inheritDoc} */
    @Override
    protected Set<Property> getProperties(Class< ? extends Object> type) {
        Set<Property> propertySet;
        if (typeDefinitions.containsKey(type)) {
            propertySet = typeDefinitions.get(type).getProperties();
        } else {
            propertySet = getPropertyUtils().getProperties(type);
        }

        List<Property> propsList = new ArrayList<>(propertySet);
        Collections.sort(propsList, new BeanPropertyComparator());

        return new LinkedHashSet<>(propsList);
    }

    class BeanPropertyComparator implements Comparator<Property> {
        @Override
        public int compare(Property p1, Property p2) {
            // p1.getType().get
            if (p1.getType().getCanonicalName().contains("util") && !p2.getType().getCanonicalName().contains("util")) {
                return 1;
            } else if (p2.getName().endsWith("Name") || p2.getName().equalsIgnoreCase("name")) {
                return 1;
            } else {
                return -1;
            }
        }
    }
}

SUMMARY:将对象转储到 YAML 文件(使用 SnakeYaml)时如何保持顺序,例如字段出现的顺序在自定义 class?

中定义

参见 this question,其中讨论了您无法通过反射获取已声明字段的行号。

再加上反射在no particular order中给你一个classes的字段,很明显在[=30=中观察声明字段的顺序是不可能的] 在运行时,因此您无法根据源代码中的 position/order 对 YAML 输出中的键进行排序,因为您不知道该顺序。

补救措施是将订单的知识传输到运行时。一些可能的方法可能是:

  • 用定义生成的 YAML 密钥位置的 weight 注释每个字段(丑陋,因为您需要在字段上注释)。
  • 通过解析 class' 定义从那里发现顺序来自动生成代码,并将其写入一些自动生成的源文件,然后使用其代码对 Representer 中的属性进行排序(此解决方案,同时避免膨胀原来class,非常复杂和精细。
  • 在 Representer 中对字段顺序进行硬编码。这基本上是以前的解决方案,但没有自动生成。容易出错,因为每次更改 class 都必须调整 Representer。

我建议不要使用任何这些解决方案。 YAML 规范明确指出,密钥顺序不得传达内容信息,如果顺序对您很重要,那么您已经违反了 YAML 规范,应该切换到更能满足您需求的格式。