Сериализация объекта в YAML на Java с использованием библиотеки змеи

У меня нет большого опыта с сериализацией. При попытке сериализовать простой объект класса ниже я получаю этот No JavaBean properties found exception из библиотеки YAML.

Вот класс:

public class MyClass {
    String value;
    public MyClass(String args) {
        value = args;
    }

    public String getValue(){
        return value;
    }
}

И вот как я сериализую с помощью SnakeYAMAL:

import java.util.HashMap;
import java.util.Map;

import org.yaml.snakeyaml.Yaml;


public class Test {

    public static void main(String[] args) {

        MyClass obj = new MyClass("this is my data");

        Map<String, Object> data = new HashMap<String, Object>();
        data.put("MyClass", obj);
        Yaml yaml = new Yaml();
        String output = yaml.dump(data);
        System.out.println(output);
    }

}

и при выполнении выдается это исключение:

Exception in thread "main" org.yaml.snakeyaml.error.YAMLException: No JavaBean properties found in MyClass
    at org.yaml.snakeyaml.introspector.PropertyUtils.getProperties(PropertyUtils.java:112) ...

Можете ли вы сказать мне, что мне не хватает при этом, или как мне сделать это правильно?

РЕДАКТИРОВАТЬ:

public class MyClass {
    String value;
    public MyClass() {}

    public String setValue(String value){
        this.value = value;
    }

    public String getValue(){
        return value;
    }
}

и если я устанавливаю значение перед его сериализацией, оно как-то работает. Как вы думаете, это правильное решение или не рекомендуемый подход?


person Johnydep    schedule 13.12.2011    source источник


Ответы (1)


SnakeYAML разработан в первую очередь для сериализации JavaBeans.

Приведенный выше пример не соответствует спецификации JavaBean. Чтобы быть JavaBean, объект должен иметь конструктор без аргументов, и каждое поле должно иметь геттер и сеттер.

Если вы перепишете свой класс как bean-компонент, SnakeYAML без проблем сериализует его. Кроме того, SnakeYAML может сериализовать общедоступные поля, поэтому, если вы измените видимость value на public, SnakeYAML найдет и сериализует его.

Если вы действительно хотите избежать изменения MyClass, вы можете явно указать SnakeYAML сериализовать свойства, доступные только для чтения, примерно так:

PropertyUtils propUtils = new PropertyUtils();
propUtils.setAllowReadOnlyProperties(true);
Representer repr = new Representer();
repr.setPropertyUtils(propUtils);
Yaml yaml = new Yaml(new Constructor(), repr);

Однако выгрузка не-JavaBean-объектов в YAML может вызвать проблемы, когда вы придете к их десериализации обратно в Object, поэтому я рекомендую использовать JavaBeans как самое простое и безопасное решение.

Изменить: Вот пример MyClass, преобразованного в JavaBean:

public class MyClass {
    String value;

    /* public, no-argument constructor */
    public MyClass() {
    }

    /* Every field has a public getter... */
    public String getValue(){
        return value;
    }

    /* ... and a public setter */
    public void setValue(String value) {
        this.value = value;
    }
}
person Chris B    schedule 13.12.2011
comment
Можете ли вы добавить очень небольшой пример преобразования этого класса в JavaBean. Я не знаю, как использовать JavaBeans, спасибо. - person Johnydep; 13.12.2011
comment
@Johnydep Я отредактировал свой ответ, включив в него пример преобразования MyClass в действительный JavaBean. - person Chris B; 13.12.2011
comment
можете ли вы подтвердить, является ли мой отредактированный код правильным способом использования сериализации YAML? благодарю вас - person Johnydep; 13.12.2011
comment
Есть ли способ заставить SnakeYAML работать с автоматически сгенерированным конструктором без аргументов, геттерами и сеттерами из Project Lombok? - person chrisinmtown; 11.05.2021