Empty yaml file must return null instead of throwing an exception when loading a JavaBean

Issue #375 resolved
Matt Kusnierz created an issue

Attempting to parse a (generated configuration) empty yaml file such as (see attachment)

using snakeyaml v1.17 and this method: org.yaml.snakeyaml.Yaml.loadAs(String, Class<C>)

throws a Constructor Exception:

org.yaml.snakeyaml.constructor.ConstructorException: Can't construct a java object for tag:yaml.org,2002:CLASSNAME; exception=No single argument constructor found for class CLASSNAME in 'string', line 4, column 1: ... ^

at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:350) ~[snakeyaml-1.17.jar:na]
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:182) ~[snakeyaml-1.17.jar:na]
at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:141) ~[snakeyaml-1.17.jar:na]
at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:127) ~[snakeyaml-1.17.jar:na]
at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:450) ~[snakeyaml-1.17.jar:na]
at org.yaml.snakeyaml.Yaml.loadAs(Yaml.java:427) ~[snakeyaml-1.17.jar:na]
at

... Caused by: org.yaml.snakeyaml.error.YAMLException: No single argument constructor found for class CLASSNAME at org.yaml.snakeyaml.constructor.Constructor$ConstructScalar.construct(Constructor.java:397) ~[snakeyaml-1.17.jar:na] at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:346) ~[snakeyaml-1.17.jar:na] ... 11 common frames omitted

However, a really empty file (without the --- ...) doesn't have this issue.

Comments (20)

  1. Matt Kusnierz reporter

    In your test, you are setting the target bean/class type as String.class; which does have a constructor that could be called with the single argument "..." which is not correct. The result of that test should have been an empty string, not string == "..."

    If you try to use a bean/class type that doesn't have a single string parameter constructor, do you get the expected results?

  2. Matt Kusnierz reporter

    Attached a failing test. It seems that the ctor(String) needs to exist even if it is not getting called with "..."

  3. Matt Kusnierz reporter

    ok agreed, the presence of the ctor(String) or not is a red-herring. Are you able to reproduce the test failure on your branch? That test fails for me on v1.17 (I can't test higher versions at the moment... corporate environment = "paperwork")

  4. Andrey Somov

    If you help me to understand your complain:

    However, a really empty file (without the --- ...) doesn't have this issue.

    I can try to look further. For me there is no change with or without --- ...

    I have updated the test. Please change it in such a way that I can understand the problem.

  5. Matt Kusnierz reporter

    The test is fine; using v1.17; this method emptyYamlTestAsObject() throws a org.yaml.snakeyaml.constructor.ConstructorException. If you can re-run this test on your build of 1.17 to confirm that I'm not going mad/doing something stupid; but can also show that the same test passes on v1.18, then we know that the issue has already been fixed.

  6. Matt Kusnierz reporter

    Ah no, I hadn't seen the update. But why do you expect this exception? Why should that throw an exception?

    Also note that the emptyYamlTestAsObject test doesn't have the "..." footer.

  7. Matt Kusnierz reporter

    Or are you saying that v1.17 DOES expect the exception, and v1.18 does NOT expect the exception?

  8. Matt Kusnierz reporter

    btw, my point about a "really empty file (without the ---...) doesn't have this issue" is that this method is fine, and doesn't throw an exception:

    @Test
        public void totallyEmptyYamlTestAsObject() {
            Yaml yaml = new Yaml();
            TestObject obj = yaml.loadAs("", TestObject.class);
            Assert.assertNull(obj);
        }
    

    Although whilst this method doesn't throw an unhandled exception; the behavior is different; I.e. returns null instead of returning an new uninitialized object (with all its attributes in their default state)

  9. Andrey Somov
    1. The reason that we ask to provide a test is exactly to avoid this kind of ping-pong communication
    2. Both versions work the same way
    3. Your last comment finally helps me to identify 2 independent issues
    4. First issue is that the YAML documents which are resolved to an empty string cause different results (exception and null) - this is a bug
    5. Second issue is that you expect nothing to be an object while now SnakeYAML returns null - this is a feature request.

    If you want to proceed I would recommend to close this issue and open another with exact description of your expectation (one by one, or just the one which is important for you).

  10. Matt Kusnierz reporter

    Thanks Andrey; and sorry for the back-and-forth comms.

    Can you confirm what the v1.8 (and head going forwards) behavior is for the empty (with header/footer) yaml parsing to a complex object? Should this throw a constructor exception or not (I assume not). And that this issue was fixed somewhere along the line between 1.7 (throws exception) and 1.8 (no longer throws exception). And with v >=1.8 the result will be to construct a new object of the correct type, and leave it in is default/initializer state.

    The issue with a truly empty file returning null vs an unpopulated new object would represent a behavioural backwards compatibility breaking change. I don't especially need this behavior to change, and so whilst conceptually I agree that this is a bug and they should produce the same results; I would understand the rationale for treading cautiously here. I'm happy to re-raise this as a separate issue/feature request if you would like, but it is not a change that I would especially be pushing for.

  11. Andrey Somov

    Thank you. Finally the bug is identified. Regardless how an empty document is defined it should return null. The fix is coming...

  12. Andrey Somov
    1. Versions 1.7 and 1.8 are far too old. No comments.
    2. If you mean 1.17 and 1.18 then both have same bug - sometimes an empty YAML document throws an exception instead of returning null
    3. It is just fixed and from version 1.19 on it should always return null for any empty document
  13. Log in to comment