通过 YAML 文件加载基于 class 的抽象对象
Loading an abstract class based object by YAML file
我想从 yaml 文件中加载包含基于抽象 class 的对象数组列表的对象。我收到此错误消息:
线程“LWJGL 应用程序”中的异常无法为 JavaBean=com.myyaml.test.ImplementationOfExampleClass@7a358cc1
创建 属性=arrayListOfAbstractObjects
在 'reader',第 1 行,第 1 列:
虚拟长:1
^
java.lang.InstantiationException
在 'reader',第 3 行,第 3 列:
- 虚拟浮动:444
^
YAML 文件
dummyLong: 1
arrayListOfAbstractObjects:
- dummyFloat: 444
- dummyDouble: 123
Java classes:
public abstract class ExampleClass {
protected ArrayList<AbstractClass> arrayListOfAbstractObjects;
protected long dummyLong = 111;
public ExampleClass() {
}
public void setArrayListOfAbstractObjects(ArrayList<AbstractClass> arrayListOfAbstractObjects) {
this.arrayListOfAbstractObjects = arrayListOfAbstractObjects;
}
public void setDummyLong(long dummyLong) {
this.dummyLong = dummyLong;
}
}
public class ImplementationOfExampleClass extends ExampleClass {
public ImplementationOfExampleClass() {
}
}
public abstract class AbstractClass {
private int dummyInt = 22;
public AbstractClass() {
}
public void setDummyInt(int dummyInt) {
this.dummyInt = dummyInt;
}
}
public class FirstImplementationOfAbstractClass extends AbstractClass {
float dummyFloat = 111f;
public FirstImplementationOfAbstractClass() {
}
public void setDummyFloat(float dummyFloat) {
this.dummyFloat = dummyFloat;
}
}
public class SecondImplementationOfAbstractClass extends AbstractClass {
double dummyDouble = 333f;
public SecondImplementationOfAbstractClass() {
}
public void setDummyDouble(double dummyDouble) {
this.dummyDouble = dummyDouble;
}
}
我的猜测是 yaml 不知道要使用哪种抽象 class 实现。 FirstImplementationOfAbstractClass 或 SecondImplementationOfAbstractClass。是否可以使用这样的 classes 通过 yaml 加载对象?
这只有在您告诉 YAML 处理器您想在 YAML 端实例化哪个 class 时才有可能。您可以使用标签执行此操作:
dummyLong: 1
arrayListOfAbstractObjects:
- !first
dummyFloat: 444
- !second
dummyDouble: 123
然后,您可以指示 YAML 处理器根据标签正确处理项目。例如。使用 SnakeYAML,你会做
class MyConstructor extends Constructor {
public MyConstructor() {
this.yamlConstructors.put(new Tag("!first"), new ConstructFirst());
this.yamlConstructors.put(new Tag("!second"), new ConstructSecond());
}
private class ConstructFirst extends AbstractConstruct {
public Object construct(Node node) {
// raw values, as if you would have loaded the content into a generic map.
final Map<Object, Object> values = constructMapping(node);
final FirstImplementationOfAbstractClass ret =
new FirstImplementationOfAbstractClass();
ret.setDummyFloat(Float.parseFloat(values.get("dummyFloat").toString()));
return ret;
}
}
private class ConstructSecond extends AbstractConstruct {
public Object construct(Node node) {
final Map<Object, Object> values = constructMapping(node);
final SecondImplementationOfAbstractClass ret =
new SecondImplementationOfAbstractClass();
ret.setDummyFloat(Double.parseDouble(values.get("dummyFloat").toString()));
return ret;
}
}
}
注意:加载内容时可以更智能,避免toString
直接处理节点内容;为了便于演示,我使用了一个愚蠢的实现。
然后,你使用这个构造函数:
Yaml yaml = new Yaml(new MyConstructor());
ExampleClass loaded = yaml.loadAs(input, ImplementationOfExampleClass.class);
节点 class 是一种转换为 Java 数据对象的 YAML 文件。我在调试器下发现它包含字段 ArrayList<E>
值。其中包含带有 YAML 文件字段(例如 dummyFloat)的 NodeTuple。所以我必须在 constructMapping(node)
方法中自己转换每个字段,然后将它们设置在例如ConstructFirst.construct(Node node)
在构建的对象上。
编辑:
So I must in constructMapping(node)
method convert on my own each field and then set them in e.g. ConstructFirst.construct(Node node)
on the constructed object.
需要将参数节点转换为 MappingNode。该方法继承自BaseConstructor.constructMapping(MappingNode节点)。 Flyx 没有添加该演员表,我不知道从哪里得到它。感谢帮助。现在可以了。但我仍然在为嵌套的抽象 classes 苦苦挣扎。也许我需要帮助,但我会努力处理自己。
另外这个 link 可能会有帮助:
我想从 yaml 文件中加载包含基于抽象 class 的对象数组列表的对象。我收到此错误消息:
线程“LWJGL 应用程序”中的异常无法为 JavaBean=com.myyaml.test.ImplementationOfExampleClass@7a358cc1
创建 属性=arrayListOfAbstractObjects在 'reader',第 1 行,第 1 列: 虚拟长:1 ^
java.lang.InstantiationException 在 'reader',第 3 行,第 3 列: - 虚拟浮动:444 ^
YAML 文件
dummyLong: 1
arrayListOfAbstractObjects:
- dummyFloat: 444
- dummyDouble: 123
Java classes:
public abstract class ExampleClass {
protected ArrayList<AbstractClass> arrayListOfAbstractObjects;
protected long dummyLong = 111;
public ExampleClass() {
}
public void setArrayListOfAbstractObjects(ArrayList<AbstractClass> arrayListOfAbstractObjects) {
this.arrayListOfAbstractObjects = arrayListOfAbstractObjects;
}
public void setDummyLong(long dummyLong) {
this.dummyLong = dummyLong;
}
}
public class ImplementationOfExampleClass extends ExampleClass {
public ImplementationOfExampleClass() {
}
}
public abstract class AbstractClass {
private int dummyInt = 22;
public AbstractClass() {
}
public void setDummyInt(int dummyInt) {
this.dummyInt = dummyInt;
}
}
public class FirstImplementationOfAbstractClass extends AbstractClass {
float dummyFloat = 111f;
public FirstImplementationOfAbstractClass() {
}
public void setDummyFloat(float dummyFloat) {
this.dummyFloat = dummyFloat;
}
}
public class SecondImplementationOfAbstractClass extends AbstractClass {
double dummyDouble = 333f;
public SecondImplementationOfAbstractClass() {
}
public void setDummyDouble(double dummyDouble) {
this.dummyDouble = dummyDouble;
}
}
我的猜测是 yaml 不知道要使用哪种抽象 class 实现。 FirstImplementationOfAbstractClass 或 SecondImplementationOfAbstractClass。是否可以使用这样的 classes 通过 yaml 加载对象?
这只有在您告诉 YAML 处理器您想在 YAML 端实例化哪个 class 时才有可能。您可以使用标签执行此操作:
dummyLong: 1
arrayListOfAbstractObjects:
- !first
dummyFloat: 444
- !second
dummyDouble: 123
然后,您可以指示 YAML 处理器根据标签正确处理项目。例如。使用 SnakeYAML,你会做
class MyConstructor extends Constructor {
public MyConstructor() {
this.yamlConstructors.put(new Tag("!first"), new ConstructFirst());
this.yamlConstructors.put(new Tag("!second"), new ConstructSecond());
}
private class ConstructFirst extends AbstractConstruct {
public Object construct(Node node) {
// raw values, as if you would have loaded the content into a generic map.
final Map<Object, Object> values = constructMapping(node);
final FirstImplementationOfAbstractClass ret =
new FirstImplementationOfAbstractClass();
ret.setDummyFloat(Float.parseFloat(values.get("dummyFloat").toString()));
return ret;
}
}
private class ConstructSecond extends AbstractConstruct {
public Object construct(Node node) {
final Map<Object, Object> values = constructMapping(node);
final SecondImplementationOfAbstractClass ret =
new SecondImplementationOfAbstractClass();
ret.setDummyFloat(Double.parseDouble(values.get("dummyFloat").toString()));
return ret;
}
}
}
注意:加载内容时可以更智能,避免toString
直接处理节点内容;为了便于演示,我使用了一个愚蠢的实现。
然后,你使用这个构造函数:
Yaml yaml = new Yaml(new MyConstructor());
ExampleClass loaded = yaml.loadAs(input, ImplementationOfExampleClass.class);
节点 class 是一种转换为 Java 数据对象的 YAML 文件。我在调试器下发现它包含字段 ArrayList<E>
值。其中包含带有 YAML 文件字段(例如 dummyFloat)的 NodeTuple。所以我必须在 constructMapping(node)
方法中自己转换每个字段,然后将它们设置在例如ConstructFirst.construct(Node node)
在构建的对象上。
编辑:
So I must in
constructMapping(node)
method convert on my own each field and then set them in e.g.ConstructFirst.construct(Node node)
on the constructed object.
需要将参数节点转换为 MappingNode。该方法继承自BaseConstructor.constructMapping(MappingNode节点)。 Flyx 没有添加该演员表,我不知道从哪里得到它。感谢帮助。现在可以了。但我仍然在为嵌套的抽象 classes 苦苦挣扎。也许我需要帮助,但我会努力处理自己。
另外这个 link 可能会有帮助: