SnakeYAML/Scala beginner

2,096 views
Skip to first unread message

sonson

unread,
Jan 18, 2012, 4:43:00 AM1/18/12
to SnakeYAML
Hello,

I am new in the SnakeYAML-world and have to to read a simple YAML-
Project-File in Scala... but my code throws an exception:
org.yaml.snakeyaml.constructor.ConstructorException: null; Can't
construct a java object for tag:yaml.org...

My code:

case class Project(name: String, url: String)
object ReadYAML {
def test() {
val yaml = new Yaml(new Constructor(classOf[Project]))
val project = yaml.load("name: abc\nurl:
def").asInstanceOf[Project]
println("YAML READ DATA: " + project)
}
}


Unfortunately I cannot find a simple Scala example anywhere on the
internet. Can you help me, what's wrong with my code?

Andrey

unread,
Jan 18, 2012, 5:24:33 AM1/18/12
to snakeya...@googlegroups.com
Hi,
use spaces before and after ':' character.

name : abc
url : bla bla

If it does not work please provide the complete error message. Otherwise it is not easy to understand the problem.

-
Andrey

sonson

unread,
Jan 18, 2012, 6:32:45 AM1/18/12
to SnakeYAML
Hello,

Thanks for your help.
The suggested spaces after the ':' character doesn't change anything.

I refactored now the SnakeYAML-part out of my project (see
https://gist.github.com/1632528 ), and get this exception:

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:
297)
at java.lang.Thread.run(Thread.java:679)
Caused by: Can't construct a java object for tag:yaml.org,
2002:test.yaml.Project; exception=java.lang.NoSuchMethodException:
test.yaml.Project.<init>()
in "<string>", line 1, column 1:
name : abc
^
at org.yaml.snakeyaml.constructor.Constructor
$ConstructYamlObject.construct(Constructor.java:333)
at
org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:
183)
at
org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:
142)
at
org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:
128)
at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:480)
at org.yaml.snakeyaml.Yaml.load(Yaml.java:399)
at test.yaml.App$.main(App.scala:13)
at test.yaml.App.main(App.scala)
... 6 more
Caused by: org.yaml.snakeyaml.error.YAMLException:
java.lang.NoSuchMethodException: test.yaml.Project.<init>()
at org.yaml.snakeyaml.constructor.Constructor
$ConstructMapping.createEmptyJavaBean(Constructor.java:220)
at org.yaml.snakeyaml.constructor.Constructor
$ConstructMapping.construct(Constructor.java:190)
at org.yaml.snakeyaml.constructor.Constructor
$ConstructYamlObject.construct(Constructor.java:331)
... 13 more
Caused by: java.lang.NoSuchMethodException: test.yaml.Project.<init>()
at java.lang.Class.getConstructor0(Class.java:2723)
at java.lang.Class.getDeclaredConstructor(Class.java:2002)
at org.yaml.snakeyaml.constructor.Constructor
$ConstructMapping.createEmptyJavaBean(Constructor.java:216)
... 15 more

Andrey

unread,
Jan 18, 2012, 6:54:28 AM1/18/12
to snakeya...@googlegroups.com
Well, SnakeYAML heavily relies on the Java reflection API.
When you use Scala you must either support the JavaBean specification by adding @BeanProperty annotation to your fields, or use BeanAccess.FIELD as described here:

sonson

unread,
Jan 18, 2012, 7:37:25 AM1/18/12
to SnakeYAML
Thank you. I tried the @BeanProperty annotation and BeanAccess.FIELD
(see https://gist.github.com/1632528 ), but always get the same
exception again. Hm, I think I will try some SnakeYAML-Java examples
before I get back to Scala programming...

Ben Darfler

unread,
Jan 18, 2012, 7:47:54 AM1/18/12
to SnakeYAML
I imagine you will have a very very hard time trying to serialize back
and forth from a Scala class. As Andrey point out its very closely
coupled with Java reflection.

In my scala code I stick with basic data types (ArrayList, Map, etc)
and that makes it manageable but there is still a lot of work to be
done to convert things from Java collections to Scala collections.

This is how I parse a YAML document that is either a list of maps or a
single map and return an option depending on if I could parse it or
not. Note, I removed the exception handling for brevity.

https://gist.github.com/1632845

On Jan 18, 7:37 am, sonson <bernhardberger...@gmail.com> wrote:
> Thank you. I tried the @BeanProperty annotation and BeanAccess.FIELD
> (seehttps://gist.github.com/1632528), but always get the same

Andrey Somov

unread,
Jan 18, 2012, 8:19:55 AM1/18/12
to snakeya...@googlegroups.com
I see now that the empty constructor is required. Scala case classes
do not define the empty constructor.

I am afraid, you have to create Java stuff first. Then you can
transform Java instances to Scala instances.
(as Ben suggested)

The proper support for Scala classes (collections, case classes etc)
is a big challenge. If would be great if someone can help here...
-
Andrey

maslovalex

unread,
Jan 18, 2012, 8:46:47 AM1/18/12
to snakeya...@googlegroups.com
Andrey is right, but in simple cases similar to yours, when case class has only properties which are in constructor (some other restrictions may apply) you can use same syntax as for immutable instances. In your case it will be just:

[ abc, def]

so 

yaml.load("[abc, def]").asInstanceOf[Project] 

Does the trick ;)


-alex
Reply all
Reply to author
Forward
0 new messages