Initializing an object without arguments
Hi! Issue is straightforward, this YAML file doesn't works:
- !!java.lang.Object
Fails with this exception:
Exception in thread "main" Can't construct a java object for tag:yaml.org,2002:java.lang.Object; exception=No single argument constructor found for class java.lang.Object
at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:349)
Instead, this works perfectly:
- !!java.lang.Object {}
Printing the result gives:
[java.lang.Object@383534aa]
(ArrayList instance with a single Object instance element)
As far as I've seen, in the first case SnakeYAML tries to create an Object instance with a single empty string argument (ie: ""), fails to find a constructor with such argument then throws the exception I quoted.
Is this intended? I'm using 1.16, I'll try with 1.17 later to see if it makes any difference.
PD: Awesome library btw!
Comments (6)
-
-
reporter Well, I thought it'd call the parameter-less constructor like the second example. But if thats how its specified, I'll just add the {} at the end if I have to write them manually. Feel free to close the issue.
-
This is confusing in the specification. The spec requires that a tag cannot be used for different node kinds (http://yaml.org/spec/1.1/current.html#id861700): each tag must specify the expected node kind (scalar, sequence, or mapping)
More information you can find in the yaml-core mailing list: https://sourceforge.net/p/yaml/mailman/message/34924083/
Unfortunately, often SnakeYAML tries its best to guess what is possible to do. Sometimes it helps sometimes does not. In your case the global tag !!java.lang.Object is not defined and SnakeYAML tries its own implementation:
- if the node is scalar -> call single argument constructor (Calling empty constructor for scalar has no meaning because the node value will be ignored.)
- if the node is mapping -> try to create a JavaBean.
I added a test to remember this use case for the future: https://bitbucket.org/asomov/snakeyaml/commits/f28e9af201c1a7f62a32ee66c410201e71d18001#chg-src/test/java/org/yaml/snakeyaml/issues/issue335/JavaLangObjectTest.java
-
reporter All right, thanks for the answers!
-
Sorry to revive an old thread, but I donāt fully understand your answer here. I have the same question. I have an abstract
KEstimation
and I am constructing a concrete implementation with SnakeYAML.The concrete implementation has two constructors (plus a no-arg constructer and all getters/setters). Thatās because there are two ways of constructing the object:
Way one works fine (yay!):
estimator: !!com.ara.jcluster.kestimation.SpectralGapK graphType: EPSILON laplacianType: SYMMETRIC knn: 25 metric: !!com.ara.archdev.dean.similarity.ParameterSetSimilarity sigma: 1
Way two works fine if I add
{}
:estimator: !!com.ara.jcluster.kestimation.SpectralGapK graphType: EPSILON laplacianType: SYMMETRIC knn: 25 objectMetric: !!com.ara.archdev.dean.similarity.ParameterSetSimilarity {}
So Iām just trying to understand what
{}
means so that I know when to use it in the future, and when to not use it. Can you clarify your answer. Specifically, the parts that confused me were:if the node is scalar -> call single argument constructor (Calling empty constructor for scalar has no meaning because the node value will be ignored.)
if the node is mapping -> try to create a JavaBean.
I donāt know why I need a āsingle argument constructorā if I donāt use
{}
. Thanks in advance for clarifying what is probably obvious. -
ā
This is mapping (in your case it will be parsed as JavaBean):
objectMetric: !!com.ara.archdev.dean.similarity.ParameterSetSimilarity {}
ā
This is scalar (scalar is no JavaBean):
objectMetric: !!com.ara.archdev.dean.similarity.ParameterSetSimilarity
- Log in to comment
This is the way how scalars are created. (Try !!java.lang.String) When a scalar is detected, SnakeYAML calls single-argument constructor for the specified class. What is wrong ? What is your expectation ?