decorators-squad/eo-yaml

hashCode() throws exception if Scalar node value `null`

Closed this issue ยท 8 comments

Describe the bug

When calling the hashCode method on YamlMapping, NullPointerException will be thrown whenever the value of any Scalar node is null.

Expected behavior

Able to call hashCode method without any exception thrown for any valid YamlMapping object.

Version used

ep-yaml version 7.0.10

Steps to reproduce

Yaml file myYaml.yaml

myField: null

Java code

public static void main(String[] args) throws IOException {
    YamlMapping mapping = Yaml.createYamlInput(
                    new File("/path/to/myYaml.yaml"))
            .readYamlMapping();
    System.out.println(mapping.hashCode());
}

Logs

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.hashCode()" because the return value of "com.amihaiemil.eoyaml.BaseScalar.value()" is null
	at com.amihaiemil.eoyaml.BaseScalar.hashCode(BaseScalar.java:72)
	at com.amihaiemil.eoyaml.BaseYamlMapping.hashCode(BaseYamlMapping.java:59)
	at com.agoda.adp.messaging.configserver.components.merger.YamlConfigMerger.main(YamlConfigMerger.java:136)

@poom-kitti thank you for reporting this. I'll assign someone to take care of it soon.

@amihaiemil I couldn't find any assignee for this task. This is either because there are no contributors with role DEV available or because the project does not have enough funds.

Please, make sure there is at least one available contributor with the required role and the project can afford to pay them.

@poom-kitti

This bug appears because, in YAML, null is a reserved keyword which will indicates the null reference (unknown object) and not the "null" String.

If you want to obtain the "null" String, you need to say: myField: "null" and not myField: null.

I'll fix the hashcode() method to check for null.

@amihaiemil Yes, I do not want "null" string, I want a fix similar to following in BaseScalar.java

/**
 * Hash Code of this scalar.
 * @return Value of hashCode() of type int.
 */
@Override
public int hashCode() {
    return isEmpty() ? 0 : this.value().hashCode();
}

Just to piggyback on this issue, may I know is it expected that when converting a Scalar node with empty String "" to String, the result is null?

E.g.,
Yaml file:

myField: ""

Java code

public static void main(String[] args) throws IOException {
    YamlMapping mapping = Yaml.createYamlInput(
                    new File("/path/to/myYaml.yaml"))
            .readYamlMapping();
    System.out.println(mapping);
}

Output:

myField: null

I am not certain how it is interpreted from the YAML spec https://yaml.org/spec/1.2.2/#72-empty-nodes. Since they say commonly then it is up to the implementor?

@poom-kitti Yes, that behaviour is intended, according to the spec which as you can see, leaves many room for interpretations. It's been like this for a long time and I would not change it.

But in your code, the value of that key will be empty string. Only when printing it out it will be turned to null.

@amihaiemil Thanks for the quick fix! ๐Ÿ˜„

@poom-kitti I think you should be able to write your own printer rather easily, since any YamlNode is actually a tree of nodes. I've been meaning to implement a visitor pattern for example, to make it easier for others to implement their own printers, but I haven't gotten to it yet...