Можете ли вы помочь мне прочитать этот файл YAML? - PullRequest
0 голосов
/ 12 июня 2018

Я новичок в YAML.Я пытался следовать учебнику (https://www.java -success.com / yaml-java-using-snakeyaml-library-tutorial / ), но он не завершен.Пока что мой YAML-файл выглядит так:

tests:
- class: tests.layers.DeleteCustomLayerTest
  param: layer
  value: Test Layer
- class: tests.routes.ViewRoutesTest
  param: project
  value: SNS Project Test

Я добавил snakeyaml в свой файл pom.xml:

<dependencies>
    <dependency>
        <groupId>org.yaml</groupId>
        <artifactId>snakeyaml</artifactId>
        <version>1.21</version>
    </dependency>

Я добавил snakeyaml-1.21.jar ко мне libsпапка.

Я создал определение для файла с именем YamlTestDataFile:

package otherObjects;
import java.util.Map;

public class YamlTestDataFile {

    private Map<String, String> tests;

    public Map<String, String> getTests() {
        return tests;
    }

    public void setTests(Map<String, String> tests) {
        this.tests = tests;
    }

     public Map<String, String> getTests(Map<String, String> tests) {
        this.tests = tests;
        return tests;
    }
}

И, наконец, утилита для чтения файла:

package utils;

import java.io.InputStream;
import org.yaml.snakeyaml.Yaml;
import otherObjects.YamlTestDataFile;

public class ReadYamlTestData {

    public static void main(String[] args) {
        YamlTestDataFile testData = null;

        Yaml yaml = new Yaml();

        try(InputStream in = ClassLoader.getSystemResourceAsStream("testData.yml")) {
        testData = yaml.loadAs(in, YamlTestDataFile.class);
    } catch(Exception ex) {
        ex.printStackTrace();
    }

    String test =  testData.getTests().get("class");
    System.out.println("test=" + test);
  }
}

Когда я запускаюэто, я получаю следующую ошибку:

Cannot create property=tests for JavaBean=otherObjects.YamlTestDataFile@5fdef03a
 in 'reader', line 1, column 1:
tests:
^
No suitable constructor with 2 arguments found for interface java.util.Map
 in 'reader', line 2, column 1:
- class: tests.layers.DeleteCust ... 

Боюсь, я понятия не имею, что происходит, и не могу найти приличных учебников, которые объясняют лучше.

Следуя дальшеиз ответа flyx я добился некоторого прогресса в этом.

Сначала я изменил файл YAML, чтобы он не использовал слово class:

tests:
- className: tests.layers.DeleteCustomLayerTest
  param: layer
  value: Test Layer
- className: tests.routes.ViewRoutesTest
  param: project
  value: SNS Project Test

Определение моего файла YAML выглядит следующим образом:

package otherObjects;
import java.util.List;

public class YamlTestDataFile {

/* public, no-argument constructor */
public YamlTestDataFile() {

}

public static final class Test {
    private String className;
    public String param;
    public String value;

    public String getClassName() { return className; }
    public void setClassName(final String value) { className = value; }

    public String getParam() { return param; }
    public void setParam(final String value) { param = value; }

    public String getValue() { return value; }
    public void setValue(final String string) { param = string; }
}

private List<Test> tests;

public List<Test> getTests() {
    return tests;
}

public void setTests(List<Test> tests) {
    this.tests = tests;
}

}

и мой читатель:

package utils;

import java.io.InputStream;
import java.util.List;

import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;

import otherObjects.YamlTestDataFile;
import otherObjects.YamlTestDataFile.Test;

public class ReadYamlTestData {

    public static void main(String[] args) {

        Constructor constructor = new Constructor(YamlTestDataFile.class);
        TypeDescription dataDesc = new TypeDescription(YamlTestDataFile.class);
        dataDesc.putListPropertyType("tests", YamlTestDataFile.Test.class);
        constructor.addTypeDescription(dataDesc);
        Yaml yaml = new Yaml(constructor);
        InputStream in = ClassLoader.getSystemResourceAsStream("testData.yml");

        YamlTestDataFile testData = null;
        try {
            testData = yaml.loadAs(in, YamlTestDataFile.class);
        }catch(Exception e) {
            System.err.println("Exception:" + e.getMessage());
            e.printStackTrace();
        }

        List<Test> tests=testData.getTests();

        for (int x=0; x<tests.size(); x++)
        System.out.println(tests.get(x).getClassName() + ", " + tests.get(x).getParam() + ", " + tests.get(x).getValue());

    }
}

Вывод в значительной степени то, что я ищу:

tests.layers.DeleteCustomLayerTest, layer, Test Layer
tests.routes.ViewRoutesTest, project, SNS Project Test

1 Ответ

0 голосов
/ 12 июня 2018

Класс, определенный в вашем коде, не соответствует структуре данных YAML.

В вашем файле YAML корнем является отображение, содержащее один ключ, tests.Значение этого ключа представляет собой последовательность сопоставлений.Вы отображаете эту конструкцию в классе, который имеет поле tests, которое является Map<String, String>.Итак, вы пытаетесь создать Java Map из последовательности YAML.SnakeYaml справедливо жалуется, что не может этого сделать.

Ваша структура YAML выглядит так, как будто вы хотите сделать что-то вроде этого:

public class YamlTestDataFile {
    public static final class Test {
        private String className;
        public String param;
        public String value;

        public String getClass() { return className; }
        public void setClass(final String value) { className = value; }
    }

    private List<Test> tests;

    public List<Test> getTests() {
        return tests;
    }

    public void setTests(List<Test> tests) {
        this.tests = tests;
    }
}

Обратите внимание, что class - это ключевое слово в Java, поэтому мыдля загрузки этого значения нужны методы получения и установки.

Стирание типа не позволяет SnakeYaml увидеть общий параметр для списка tests.Следовательно, мы должны сказать ему, что это список Test.Давайте изменим код загрузки соответствующим образом:

Constructor constructor = new Constructor(YamlTestDataFile.class);
TypeDescription dataDesc = new TypeDescription(YamlTestDataFile.class);
dataDesc.putListPropertyType("tests", YamlTestDataFile.Test.class);
constructor.addTypeDescription(dataDesc);
Yaml yaml = new Yaml(constructor);
InputStream in = ClassLoader.getSystemResourceAsStream("testData.yml");
testData = yaml.loadAs(in, YamlTestDataFile.class);

Подсказка: код не проверен.

...