@@ -39,10 +39,12 @@ Compatibility warning: New version of the parser
3939
4040Since version 0.4.0, two implementations of the parser are available:
4141
42- * `v1 `: the *classic * implementation of `javaobj `, with a work in progress
42+ * `` v1 `` : the *classic * implementation of `` javaobj ` `, with a work in progress
4343 implementation of a writer.
44- * `v2 `: the *new * implementation, a port of `jdeserialize ` with support of the
45- object transformer (with a new API) and the numpy arrays.
44+ * ``v2 ``: the *new * implementation, which is a port of the Java project
45+ [``jdeserialize ``](https://github.com/frohoff/jdeserialize/),
46+ with support of the object transformer (with a new API) and of the ``numpy ``
47+ arrays loading.
4648
4749
4850Compatibility Warning: object transformer
@@ -88,51 +90,136 @@ Unmarshalling of Java serialised object:
8890
8991.. code-block :: python
9092
91- import javaobj
93+ import javaobj
9294
93- with open (" obj5.ser" , " rb" ) as fd:
94- jobj = fd.read()
95+ with open (" obj5.ser" , " rb" ) as fd:
96+ jobj = fd.read()
9597
96- pobj = javaobj.loads(jobj)
97- print (pobj)
98+ pobj = javaobj.loads(jobj)
99+ print (pobj)
98100
99- Or, you can use Unmarshaller object directly:
101+ Or, you can use `` JavaObjectUnmarshaller `` object directly:
100102
101103.. code-block :: python
102104
103- import javaobj
105+ import javaobj
104106
105- with open (" objCollections.ser" , " rb" ) as fd:
106- marshaller = javaobj.JavaObjectUnmarshaller(fd)
107- pobj = marshaller.readObject()
107+ with open (" objCollections.ser" , " rb" ) as fd:
108+ marshaller = javaobj.JavaObjectUnmarshaller(fd)
109+ pobj = marshaller.readObject()
108110
109- print (pobj.value, " should be" , 17 )
110- print (pobj.next, " should be" , True )
111+ print (pobj.value, " should be" , 17 )
112+ print (pobj.next, " should be" , True )
111113
112- pobj = marshaller.readObject()
114+ pobj = marshaller.readObject()
113115
114116
115- The objects and methods provided by `javaobj ` module are shortcuts to the
116- `javaobj.v1 ` package
117+ **Note: ** The objects and methods provided by ``javaobj `` module are shortcuts
118+ to the ``javaobj.v1 `` package, for Compatibility purpose.
119+ It is **recommended ** to explicitly import methods and classes from the ``v1 ``
120+ (or ``v2 ``) package when writing new code, in order to be sure that your code
121+ won't need import updates in the future.
117122
118123
119124Usage (V2 implementation)
120125=========================
121126
122- Unmarshalling of Java serialised object:
127+ The following methods are provided by the ``javaobj.v2 `` package:
128+
129+ * ``load(fd, *transformers, use_numpy_arrays=False) ``:
130+ Parses the content of the given file descriptor, opened in binary mode (`rb `).
131+ The method accepts a list of custom object transformers. The default object
132+ transformer is always added to the list.
133+
134+ The ``use_numpy_arrays `` flag indicates that the arrays of primitive type
135+ elements must be loaded using ``numpy `` (if available) instead of using the
136+ standard parsing technic.
137+
138+ * ``loads(bytes, *transformers, use_numpy_arrays=False) ``:
139+ This the a shortcut to the ``load() `` method, providing it the binary data
140+ using a ``BytesIO `` object.
141+
142+ **Note: ** The V2 parser doesn't have the marshalling capability.
143+
144+ Sample usage:
123145
124146.. code-block :: python
125147
126- import javaobj.v2 as javaobj
148+ import javaobj.v2 as javaobj
127149
128- with open (" obj5.ser" , " rb" ) as fd:
129- jobj = fd.read( )
150+ with open (" obj5.ser" , " rb" ) as fd:
151+ pobj = javaobj.load(fd )
130152
131- pobj = javaobj.loads(jobj)
132- print (pobj)
153+ print (pobj.dump())
133154
134155
135156 Object Transformer
136157-------------------
137158
138- WIP
159+ An object transformer can be called during the parsing of a Java object
160+ instance or while loading an array.
161+
162+ The Java object instance parsing works in two main steps:
163+
164+ 1. The transformer is called to create an instance of a bean that inherits
165+ ``JavaInstance ``.
166+ 2. The latter bean is then called:
167+ * When the object is written with a custom block data
168+ * After the fields and annotations have been parsed, to update the content of
169+ the Python bean.
170+
171+ Here is an example for a Java ``HashMap `` object. You can look at the code of
172+ the ``javaobj.v2.transformer `` module to see the whole implementation.
173+
174+ .. code-block :: python
175+
176+ class JavaMap (dict , javaobj .v2 .beans .JavaInstance ):
177+ """
178+ Inherits from dict for Python usage, JavaInstance for parsing purpose
179+ """
180+ def __init__ (self ):
181+ # Don't forget to call both constructors
182+ dict .__init__ (self )
183+ JavaInstance.__init__ (self )
184+
185+ def load_from_instance (self , instance , indent = 0 ):
186+ # type: ( JavaInstance , int ) -> bool
187+ """
188+ Load content from a parsed instance object
189+
190+ :param instance: The currently loaded instance
191+ :param indent: Indentation to use while logging
192+ :return: True on success
193+ """
194+ # Maps have their content in their annotations
195+ for cd, annotations in instance.annotations.items():
196+ # Annotations are associated to their definition class
197+ if cd.name == " java.util.HashMap" :
198+ # We are in the annotation created by the handled class
199+ # Group annotation elements 2 by 2
200+ # (storage is: key, value, key, value, ...)
201+ args = [iter (annotations[1 :])] * 2
202+ for key, value in zip (* args):
203+ self [key] = value
204+
205+ # Job done
206+ return True
207+
208+ # Couldn't load the data
209+ return False
210+
211+ class MapObjectTransformer (javaobj .v2 .api .ObjectTransformer ):
212+ def create_instance (self , classdesc ):
213+ # type: ( JavaClassDesc ) -> Optional [ JavaInstance ]
214+ """
215+ Transforms a parsed Java object into a Python object
216+
217+ :param classdesc: The description of a Java class
218+ :return: The Python form of the object, or the original JavaObject
219+ """
220+ if classdesc.name == " java.util.HashMap" :
221+ # We can handle it
222+ return JavaMap()
223+ else :
224+ # Return None if not handled
225+ return None
0 commit comments