Initializing an object without arguments

Issue #335 invalid
Dust Contributor created an issue

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)

  1. Andrey Somov

    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 ?

  2. Dust Contributor 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.

  3. Andrey Somov

    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

  4. Wesley Neill

    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.

  5. Andrey Somov

    ā€Œ

    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

  6. Log in to comment