marcusaram / snakeyaml

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

Load failures for array type fields #21

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
How do you load objects that have arrays as fields? This example below
fails to load. But the dump() succeeds.

<code>
public class Temp {
    public static void main(String[] args) {
        A a = new A();
        a.setNames(new String[]{"a", "b", "c"});

        Yaml yaml = new Yaml();
        String s = yaml.dump(a);
        System.out.println(s);

        Object result = yaml.load(s);
        System.out.println(result);
    }

    public static class A {
        String[] names;

        public String[] getNames() {
            return names;
        }

        public void setNames(String[] names) {
            this.names = names;
        }

        public String getName(int index) {
            return names[index];
        }

        public void setName(int index, String name) {
            this.names[index] = name;
        }
    }
}
</code>

Error:
<code>
Exception in thread "main" Can't construct a java object for
tag:yaml.org,2002:test.Temp$A; exception=Cannot create property=names for
JavaBean=test.Temp$A@b8f82d; argument type mismatch
 in "<reader>", line 0, column 0

    at
org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constru
ctor.java:283)
    at
org.yaml.snakeyaml.constructor.BaseConstructor.callConstructor(BaseConstructor.j
ava:175)
    at
org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.j
ava:158)
    at
org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor
.java:117)
    at
org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.jav
a:103)
    at org.yaml.snakeyaml.Loader.load(Loader.java:39)
    at org.yaml.snakeyaml.Yaml.load(Yaml.java:140)
    at test.Temp.main(Temp.java:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
a:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Caused by: org.yaml.snakeyaml.error.YAMLException: Cannot create
property=names for JavaBean=test.Temp$A@b8f82d; argument type mismatch
    at
org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2nd
Step(Constructor.java:227)
    at
org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructo
r.java:138)
    at
org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constru
ctor.java:281)
    ... 12 more
Caused by: java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
a:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at org.yaml.snakeyaml.introspector.MethodProperty.set(MethodProperty.java:20)
    at
org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2nd
Step(Constructor.java:225)
    ... 14 more
</code>

Original issue reported on code.google.com by ashwin.j...@gmail.com on 18 Sep 2009 at 10:08

GoogleCodeExporter commented 9 years ago
Part of the problem is because I'm not clear on how to model array types in 
JavaBeans.

Original comment by ashwin.j...@gmail.com on 18 Sep 2009 at 10:21

GoogleCodeExporter commented 9 years ago
Arrays are a very weak type:
1) at runtime the type of members is lost (byte[] looks the same as int[])
2) equals() and hashcode() and toString() leave much to be desired
3) Reflection API does not provide a lot of support

Because of these and other limitations arrays are not fully supported in 
SnakeYAML. 
Use Collections.

If you really want arrays support take a look at the source code and feel free 
to 
contribute a proposal.

Original comment by py4fun@gmail.com on 19 Sep 2009 at 8:01

GoogleCodeExporter commented 9 years ago
You will find that the array type is accessible as demonstrated by the sample 
code:

=============

import java.lang.reflect.*;
import java.util.*;

public class Test{
    String[] names;
    int id;
    HashMap something;

    public static void main(String[] args){
        Field[] fields = Test.class.getDeclaredFields();

        System.out.println("Fields: " + fields.length);

        for(Field f : fields){
            System.out.println("Field: " + f.getName() + ", Type: " + f.getType() + ", Array:
" + f.getType().isArray());
        }
    }
}
=============

Result:
C:\_Dump\2\j>java Test
Fields: 3
Field: names, Type: class [Ljava.lang.String;, Array: true
Field: id, Type: int, Array: false
Field: something, Type: class java.util.HashMap, Array: false

=============

Notice the "[Ljava.lang.String" for "names".

Also, on the Sun JDK, the order of fields is preserved, even though the 
JavaDocs says
that no field & method order is guaranteed. It should be true for most JDKs 
too, I think.

Original comment by ashwin.j...@gmail.com on 20 Sep 2009 at 7:12

GoogleCodeExporter commented 9 years ago
And to do the reverse -
http://www.java2s.com/Code/Java/Language-Basics/ArrayReflectioncreateinstance.ht
m

Original comment by ashwin.j...@gmail.com on 21 Sep 2009 at 5:30

GoogleCodeExporter commented 9 years ago
I see the point now. I will have a look.

Original comment by py4fun@gmail.com on 22 Sep 2009 at 3:51

GoogleCodeExporter commented 9 years ago
Fixed: http://code.google.com/p/snakeyaml/wiki/readme#History

Original comment by py4fun@gmail.com on 22 Sep 2009 at 4:19

GoogleCodeExporter commented 9 years ago
Cool, that was quick!

Original comment by ashwin.j...@gmail.com on 22 Sep 2009 at 5:15