UcasRichard / snakeyaml

Automatically exported from code.google.com/p/snakeyaml
Apache License 2.0
0 stars 0 forks source link

Cannot combine merge operator (<<) and custom types. #100

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Make a custom Java class representing some Data. I used the following:
public class Data {
    protected int a, b;
    // getters and setters omitted for brevity
    public String toString () {
        return "Data ("+a+","+b+")";
    }
}

2. Make a YAML file representing two objects in a list. The first will be a 
"template", and will be referred to by the anchor &id. The second will use the 
merge (<<) to merge the content of the anchor. Example given is proposed syntax 
only as there doesn't seem to be any documentation on this:
[YAML FILE]
--- 
- !!Data 
  &id001 
  a: 1 
  b: 1 
- !!Data 
  <<: *id001 
  b: 3 
[END YAML FILE]

3. Attempt to load the YAML file as a list of the Data type, then print the 
elements of that List to System.out .

What is the expected output? What do you see instead?
Expected:
Data(1,1)
Data(1,3)

Received:
Error message:
Exception in thread "main" Can't construct a java object for 
tag:yaml.org,2002:Data; exception=Cannot create property=<< for JavaBean=Data 
(0,0); Unable to find property '<<' on class: Data
in "<reader>", line 6, column 3:
    - !!Data
      ^

What version of the product are you using? On what operating system?
SnakeYaml 1.7 in JVM 1.6 on Windows XP

Please provide any additional information below.

Original issue reported on code.google.com by JordanAn...@gmail.com on 7 Jan 2011 at 3:19

GoogleCodeExporter commented 9 years ago
Can you please check whether the test meets your expectations:
http://code.google.com/p/snakeyaml/source/browse/src/test/java/org/yaml/snakeyam
l/issues/issue100/MergeJavaBeanTest.java

Original comment by py4fun@gmail.com on 7 Jan 2011 at 4:03

GoogleCodeExporter commented 9 years ago
The linked test matches my expectations. Additionally, you may wish to include 
a method to check the override portions of the merge operator. This is the 
third example here: http://yaml.org/type/merge.html

Example test case:

    /**
     * Test that the merge-override works correctly in the case of custom classes / data types.
     * Two base objects are specified:
     *    id001 refers to Data ( 11, "id123" )
     *    id002 refers to Data ( 37, null )  with a literal null value
     * The third object is specified as having the properties of id001, with the properties of
     * id002 overriding where they conflict.
     *    Data ( 37, "id123" )
     */
    @SuppressWarnings("unchecked")
    public void testMergeAndDeviateOverride() throws IOException {
        String input = "- &id001 !!org.yaml.snakeyaml.issues.issue100.Data {age: 11, id: id123}\n- &id002 !!org.yaml.snakeyaml.issues.issue100.Data {age: 37}\n- <<: [ *id002, *id001 ]";
        System.out.println(input);
        Yaml yaml = new Yaml();
        Set<String> ids = new HashSet<String>();
        try {
            List<Data> list = (List<Data>) yaml.load(input);

            // First object: Data ( 11, "id123" )
            assertEquals ( 11, list.get(0).getAge() );
            assertEquals ( "id123", list.get(0).getId() );

            // Second object: Data ( 37, null )
            assertEquals ( 37, list.get(1).getAge() );
            assertEquals ( null, list.get(1).getId() );

            // Third object: Data ( 37, "id123" )
            assertEquals ( 37, list.get(2).getAge() );
            assertEquals ( "id123", list.get(2).getId() );
        } catch (Exception e) {
            // TODO issue 100
        }
    }

Optional additional test cases could check the following, depending on how 
strict you want to be, and what the YAML specification states (I have not read 
the specification thoroughly):

1. Check that, in addition to correct overrides, further assignments can be 
made to the merged object. This would be similar to the given test case above, 
with "\n    id:id456" appended to the YAML string. The expected result is that 
the merged object is then Data ( 37, "id456" )

2. Check that assignments occur a specified number of times. Some properties 
perform additional work beyond just setting a reference, and behaviour may be 
unintentionally affected if a setter is called more than once due to a merge.

An example of a bad side-effect (this isn't good coding practice, just a simple 
example):
    public void setLocalPort ( int port ) {
        socket = new ServerSocket ( port );
    }

Setting port to two different values could lead to a non-obvious orphaned 
ServerSocket. Similar things could happen with other OS resources, such as IO 
streams, file handles, etc.

My opinion at the moment is that it would be best if, conceptually at least, 
the map representing the merged object were constructed, and when the mapping 
has been completely parsed then the "final" values of the specified fields are 
set, exactly once. This avoids the above issue but may (or may not) be more 
difficult.

Whatever the case, the behaviour chosen should be documented well, probably in 
the Wiki.

Original comment by JordanAn...@gmail.com on 7 Jan 2011 at 4:28

GoogleCodeExporter commented 9 years ago
This issue was updated by revision b9fce94240.

see issue100-1.yaml. If tag specified we now correctly create beans by merging 
existing maps.
More tests for this case are welcome ;)

Original comment by alexande...@gmail.com on 11 Jan 2011 at 9:23

GoogleCodeExporter commented 9 years ago
Since the !!merge tag is only for the '<<' scalar the issue is simpler and we 
can consider the failure in release 1.7 as a bug.
This is, for instance, how the a map may look like:

    - !!map # Merge multiple maps
      !!merge ignore: [ *CENTER, *BIG ]
      label: center/big

http://code.google.com/p/snakeyaml/source/browse/src/test/resources/issues/issue
100-2.yaml

'<<' is not required since the explicit tag is used.

Examples can be found here: 
http://code.google.com/p/snakeyaml/source/browse/src/#src%2Ftest%2Fjava%2Forg%2F
yaml%2Fsnakeyaml%2Fissues%2Fissue100

The fix will be delivered in release 1.8

Original comment by py4fun@gmail.com on 13 Jan 2011 at 12:47

GoogleCodeExporter commented 9 years ago
Additional information can be found here:

https://groups.google.com/d/topic/snakeyaml-core/Ct0HSaLToVw/discussion

Original comment by aso...@gmail.com on 15 Jan 2011 at 10:49