I have an error while reading a file
Exception in thread "main" java.lang.ClassCastException: java.lang.String can not be cast to java.util.ArrayList.
Why does it not occur? I'm using YamlSnake lib
Person.java
:
public class Person
{
int id;
String fname;
String lname;
int age;
public Person(int id, String fname, String lname, int age)
{
this.id = id;
this.fname = fname;
this.lname = lname;
this.age = age;
}
}
yaml.java
:
@Override
public ArrayList<Person> Read() {
ArrayList<Person> pp = new ArrayList<Person>();
try
{
FileReader fr = new FileReader("d:\\Person.yml");
BufferedReader br = new BufferedReader(fr);
String str=br.readLine();
Yaml yml = new Yaml();
pp=(ArrayList<Person>) yml.load(str);
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return pp;
}
Person.yaml
:
-id:2 fname:uu lname:uu age:45
You have errors in your YAML syntax. In a block mapping, only one key is allowed per line. Also, there must be a space after both -
and :
for them to be recognized as YAML special characters. Try:
- id: 2
fname: uu
lname: uu
age: 45
If you want to keep it in one line, you can use a flow map instead:
- {id: 2, fname: uu, lname: uu, age: 45 }
Now the second problem is type erasure. You cannot tell SnakeYaml to load the YAML sequence into an ArrayList<Person>
because at runtime, even if you tell SnakeYaml you want to have an ArrayList
, it is impossible to determine the generic parameter Person
. However, SnakeYaml does provide a possibility to overcome that restriction - alas, it requires you to change your YAML.
Let this be your YAML:
persons:
- id: 2
fname: uu
lname: uu
age:45
Notice that I placed a YAML mapping as root element, which only contains a key persons
whose value is the original YAML.
Now, in Java, declare a class that matches this root element:
class Root {
List<Person> persons;
}
As before, type erasure prevents SnakeYaml to automatically determine the generic parameter of the type of persons
at runtime. But now, we can use a TypeDescription
to carry that information. Here's the code:
@Override
public List<Person> Read() {
Constructor c = new Constructor(Root.class);
TypeDescription td = new TypeDescription(Root.class);
td.putListPropertyType("persons", Person.class);
c.addTypeDescription(td);
Yaml yaml = new Yaml(c);
try {
FileReader fr = new FileReader("d:\\Person.yml");
Root r = yaml.loadAs(fr, Root.class);
fr.close();
return r.persons;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Collections.<Person>emptyList();
}
Beware of bugs in above code, I didn't test it.