yaml YAMLException: как настроить с помощью SnakeYaml?

Я пытаюсь использовать библиотеку SnakeYaml для настройки моего проекта с использованием файла YAML. Я уже читал этот пример: здесь

Я следую этой структуре, и у меня есть эти файлы:

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

person Emanuele Vannacci    schedule 08.04.2017    source источник


Ответы (1)


Проблема в том, что вы говорите SnakeYaml преобразовать число (60) в объект ServiceConfig. Так как ServiceConfig не имеет конструктора, принимающего ровно один аргумент, SnakeYaml не знает, как это сделать.

Чтобы вдаваться в подробности, это неудачная строка:

  tickTupleFrequency: 60

tickTupleFrequency вот ключ от Map<String, ServiceConfig>. Загрузить его как строку не проблема, поэтому SnakeYaml делает это. Теперь есть значение 60. Это должно быть преобразовано в объект ServiceConfig, чтобы поместиться на карту. Как 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.

person flyx    schedule 10.04.2017