Sometimes, applications, are necessary to interact with the serialized form of a different language. This usually happens in the persistence layer. Ideally, the form chosen for persistence should be cross platform (i.e protobufs), but unfortunately the reality is that sometimes the developer has no control over it or he/she needs to deal with third party systems, which they use a different serialized form than his/her language of choice supports.
This article, is about such a scenario and presents in simple steps how someone can deserialize (unPickle) in Java, a Python pickled object [see: Python Pickle].
Outlining the main steps someone has to follow below:
- Have a dependency to Jython, which will be called from inside Java
- Create a Java interface, which will act as a proxy between the Python/Jython and Java.
- Create a stub class of the Python object, which the serialized form represents, and make sure you extend the above Java interface defined in step two. Also, this python class will have to implement all the methods for the specified interface
- From your Java code use the cPickle Jython API to un-pickle the serialized object into your java interface
The below example demonstrates the steps defined above.
The Python object
Let’s assume the python object that gets pickled is the below
Knowing how the python object looks like makes it a lot easier to define the Jython stub. If the object is not known, the developer will have to reverse engineer the serialized pickle and create his/her stub.
If an instance of the above object gets pickled it will look similar to:
If using maven add a dependency to Jython.
Java Interface acting as a proxy
Next step is to define a Java interface which acts as a proxy between Jython and Java. You can read more about this here
The interface we defined is the below:
We need to create a stub of the original object, which will extend the java interface we have defined. That stub is the Jython object that will store the serialized object after unpickling and before returning to Java.
In our case this can look like:
Note here that we import the actual Java interface we have defined and the python objects implements that interface.
Some minor caveats to be aware of, at this step, is that this python object needs to be in your Jython’s classpath, or module directory even better. This can be achieved by various ways, but the easiest would be:
- Add the module directory in the environment variable JYTHONENV
- Programmatically from Java add the directory that the module resides to python.path (i.e System.setProperty( “python.path”, “/pythonModuleDir” ) )
UnPickle the object
The final step is to unpickle and use the object in Java. A sample code to do that is: