PyYaml to SnakeYaml --- AWT-EventQueue-0" Can't construct a java object for tag:yaml.org,2002:java/object:

1.4k views Asked by At

I am passing Yaml created with PyYaml to SnakeYaml and Snakeyaml does not seem to recognize anything beyond the first line where !! exists and python/object is declared. I already have identical objects setup in Java. Is there an example out there that shows a loadAll into an object array where the object type is asserted or assigned?


Good call... was away from the computer when I originally posted.

Here is the data from PyYaml that I am trying to use SnakeYaml to get into a Java application:

--- !!python/object:dbmethods.Project.Project {dblogin: kirtstrim7900, dbname: 92218kirtstrim_wfrogls,dbpw: 1234567895#froggy, preference1: '', preference2: '', preference3: '', projName: CheckPoint Firewall Audit - imp, projNo: 1295789430544+CheckPoint Firewall Audit - imp, projectowner: [email protected],result1label: Evidence, result2label: Recommend, result3label: Report, resultlabel: Response,role: owner, workstep1label: Objective, workstep2label: Policy, workstep3label: Guidance,worksteplabel: Procedure}

Not just a single instance of the above, but several objects, so need to use loadAll in SnakeYaml.... unless somebody knows better.

As for the code, this is all I have from SnakeYaml docs:

for (Object data : yaml.loadAll(sb.toString())) {   
    System.out.println(data.toString());
}

Then, this error is thrown:

Exception in thread "AWT-EventQueue-0" Can't construct a java object for tag:yaml.org,2002:java/object: ...... 
Caused by: org.yaml.snakeyaml.error.YAMLException: Class not found: ......

As you can see from the small code snippet, EVEN without all this information supplied, anybody who knows the answer about how to cast an object arbitrarily could PROBABLY answer the question.

Thx.

Parsed off the two exclamation points (!!) at the beginning of each entry and now I get: mapping values are not allowed here in "", line 1, column 73:

as an error. The whole point of using YAML was to reduce coding related to parsing. If I have to turn around and parse incoming and outgoing code for whatever reason, then YAML sucks!! And will gladly revert back XML or anything else that will allow a python middleware to talk to a java application.

2

There are 2 answers

0
kirtcathey On BEST ANSWER

Fixed. YAML sucks, so don't use it. All kinds of Google results about how SnakeYAML is derived from PyYaml and what-not, but nobody clearly states exactly what dumps format from PyYaml works with what loadAll routines with SnakeYAML.

Also, performance with YAML is horrid, JSON is far simpler and easier to implement. In Python, where our middleware resides (and most crunching occurs), YAML takes almost twice the time to process than JSON!!

If you are using Python 2.6 or greater, just

 import json
    json_doc = json.dumps(projects, default=convert_to_builtin_type)
                    print json_doc
  def convert_to_builtin_type(obj):
     print 'default(', repr(obj), ')'
     # Convert objects to a dictionary of their representation
     d = { '__class__':obj.__class__.__name__,
          '__module__':obj.__module__,
          }
     d.update(obj.__dict__)
     return d

Then on the Java client (loading) side, use GSon -- this took a lot of head-scratching and searches to figure out because ALL examples on the 'net are virtually useless. Every blogger with 500 ads per page shows you how to convert one single, stupid object and last time I created an app, I used lists, arrays, or anything that held more than one object!!

try {
    serverAddress = new URL("http://127.0.0.1:5000/projects/" + ruser.getUserEmail()+"+++++"+ruser.getUserHash());
    //set up out communications stuff
    connection = null;

    //Set up the initial connection
    connection = (HttpURLConnection)serverAddress.openConnection();
    connection.setRequestMethod("GET");
    connection.setDoOutput(true);
    connection.setReadTimeout(100000);

    connection.connect();

    //get the output stream writer and write the output to the server
    //not needed in this example

    rd  = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    sb = new StringBuilder();

    while ((line = rd.readLine()) != null)
    {
       sb.append(line + '\n');
    }
    String mystr = sb.toString();
    // Now do the magic.
    Gson gson = new Gson();
    projectData = gson.fromJson(mystr, ProjectData[].class);    
} catch (MalformedURLException e) {
    e.printStackTrace();
} catch (ProtocolException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}
finally
{
    //close the connection, set all objects to null
    connection.disconnect();
    rd = null;
    sb = null;
    connection = null;
}


return projectData;

Done! In a nutshell - YAML sucks and use JSON!! Also, the http connection code is mostly snipped off of this site...now I need to figure out https.

1
Andrey On

To achieve the same result you may:

  • configure PyYAML to skip the tag (exactly as you did with the comment "Convert objects to a dictionary of their representation")
  • configure SnakeYAML to create the object you expect (exactly as you did with "projectData = gson.fromJson(mystr, ProjectData[].class); ")

If you are lost (before you say "it sucks") you may ask a question in the corresponding mailing lists. It may help you to find a proper solution in the future.