yaml YAMLException:如何使用SnakeYaml进行配置?

时间:2017-04-08 17:18:02

标签: java yaml snakeyaml

我尝试使用SnakeYaml库使用YAML文件配置我的项目。 我已经阅读了这个例子:Here

我遵循这个结构,我有这些文件:

config/statisticsConfig.yml

statisticsTopologyParams:
   tickTupleFrequency: 60

   hourlyStatistics: 
     windowLength: 3600
     emitFrequency: 60 

   dailyStatistics: 
     windowLength: 86400
     emitFrequency: 3600 

Configuration.java

 public class Configuration {
     Map<String, ServiceConfig> statisticsTopologyParams;

     public Configuration() {
     }

     @Override
     public String toString() {
         return "YamlConfig{" +
                 "statistics=" + statisticsTopologyParams +
                 '}';
     }

     public Map<String, ServiceConfig> getStatisticsTopologyParams() {
         return statisticsTopologyParams;
     }

     public void setStatisticsTopologyParams(Map<String,        ServiceConfig> statisticsTopologyParams) {
         this.statisticsTopologyParams = statisticsTopologyParams;
     }

}

ServiceConfig.java

public class ServiceConfig {

    private Integer tickTupleFrequency;
    private Map<String, Integer> hourlyStatistics;
    private Map<String, Integer> dailyStatistics;

    public ServiceConfig() {
    }

    public Integer getTickTupleFrequency() {
        return tickTupleFrequency;
    }

    public void setTickTupleFrequency(Integer tickTupleFrequency) {
        this.tickTupleFrequency = tickTupleFrequency;
    }

    public Map<String, Integer> getHourlyStatistics() {
        return hourlyStatistics;
    }

    public void setHourlyStatistics(Map<String, Integer> hourlyStatistics) {
        this.hourlyStatistics = hourlyStatistics;
    }

    public Map<String, Integer> getDailyStatistics() {
        return dailyStatistics;
    }

    public void setDailyStatistics(Map<String, Integer> dailyStatistics) {
        this.dailyStatistics = dailyStatistics;
    }
}

YamlConfigRunner.java

public class YamlConfigRunner {


    public Configuration getConfiguration(String filePath) throws IOException {


        Constructor constructor = new Constructor(Configuration.class);
        Yaml yaml = new Yaml(constructor);

        try (InputStream in = Files.newInputStream(Paths.get(filePath))) {
            Configuration config = yaml.loadAs(in, Configuration.class);
            System.out.println(config.toString());
            return config;
        }
    }

}

但是我得到了例外:

null; Can't construct a java object for tag:yaml.org,2002:org.uniroma2.sdcc.Utils.Configuration; exception=Cannot create property=statisticsTopologyParams for JavaBean=YamlConfig{statistics=null}; No single argument constructor found for class org.uniroma2.sdcc.Utils.ServiceConfig;  in 'reader', line 1, column 1:
statisticsTopologyParams:


 Caused by: org.yaml.snakeyaml.error.YAMLException: No single argument constructor found for class org.uniroma2.sdcc.Utils.ServiceConfig

1 个答案:

答案 0 :(得分:0)

问题在于您告诉SnakeYaml将数字(60)转换为ServiceConfig对象。由于ServiceConfig没有一个只接受一个参数的构造函数,因此SnakeYaml不知道如何做到这一点。

详细说明,这是失败的一行:

  tickTupleFrequency: 60

tickTupleFrequency这是Map<String, ServiceConfig>的关键。将它作为String加载是没有问题的,所以SnakeYaml会这样做。现在,有一个值60。必须将其转换为ServiceConfig对象以适合Map。 SnakeYaml应该如何做到这一点?它不知道,因此产生错误。

您似乎忘记将地图级别添加到YAML,因为tickTupleFrequency和以下键都是ServiceConfig对象的所有字段。也许这就是你真正想要的东西:

statisticsTopologyParams:
  My fancy ServiceConfig:
    tickTupleFrequency: 60

    hourlyStatistics: 
      windowLength: 3600
      emitFrequency: 60 

    dailyStatistics: 
      windowLength: 86400
      emitFrequency: 3600

现在,My fancy ServiceConfig将成为Map<String, ServiceConfig>中的关键字,并且包含的​​地图将作为ServiceConfig对象加载。