GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing pypi.org — javaobj-py3 javaobj-py3 0.6.1Module for serializing and de-serializing Java objects. pip install javaobj-py3 javaobj-py3python-javaobj is a python library that provides functions for reading and
writing Java objects serialized or to be deserialized by The About this repositoryThis project is a fork of python-javaobj by Volodymyr Buell, originally from Google Code and now hosted on GitHub. This fork intends to work both on Python 2.7 and Python 3.4+. Compatibility WarningsNew implementation of the parser
Since version 0.4.0, three implementations of the parser are available:
You can use the You can use the For new development, you should use the Object transformers V1
As of version 0.2.0, the notion of object transformer from the original project as been replaced by an object creator. The object creator is called before the deserialization. This allows to store the reference of the converted object before deserializing it, and avoids a mismatch between the referenced object and the transformed one. Object transformers V2
The Object transformers V3
The Bytes arrays
As of version 0.2.3, bytes arrays are loaded as a Custom Transformer
A new transformer API has been proposed to handle objects written with a custom Java writer. You can find a sample usage in the Custom Transformer section in this file. Features
Requirements
Usage (V1 implementation)Un-marshalling of Java serialised object: import javaobj
with open("obj5.ser", "rb") as fd:
jobj = fd.read()
pobj = javaobj.loads(jobj)
print(pobj)
Or, you can use import javaobj
with open("objCollections.ser", "rb") as fd:
marshaller = javaobj.JavaObjectUnmarshaller(fd)
pobj = marshaller.readObject()
print(pobj.value, "should be", 17)
print(pobj.next, "should be", True)
pobj = marshaller.readObject()
Note: The objects and methods provided by Usage (V2 implementation)The following methods are provided by the
Note: The V2 parser doesn't have the marshalling capability. Sample usage: import javaobj.v2 as javaobj
with open("obj5.ser", "rb") as fd:
pobj = javaobj.load(fd)
print(pobj.dump())
Object TransformerAn object transformer can be called during the parsing of a Java object instance or while loading an array. The Java object instance parsing works in two main steps:
Here is an example for a Java class JavaMap(dict, javaobj.v2.beans.JavaInstance):
"""
Inherits from dict for Python usage, JavaInstance for parsing purpose
"""
def __init__(self):
# Don't forget to call both constructors
dict.__init__(self)
JavaInstance.__init__(self)
def load_from_blockdata(self, parser, reader, indent=0):
"""
Reads content stored in a block data.
This method is called only if the class description has both the
`SC_EXTERNALIZABLE` and `SC_BLOCK_DATA` flags set.
The stream parsing will stop and fail if this method returns False.
:param parser: The JavaStreamParser in use
:param reader: The underlying data stream reader
:param indent: Indentation to use in logs
:return: True on success, False on error
"""
# This kind of class is not supposed to have the SC_BLOCK_DATA flag set
return False
def load_from_instance(self, indent=0):
# type: (int) -> bool
"""
Load content from the parsed instance object.
This method is called after the block data (if any), the fields and
the annotations have been loaded.
:param indent: Indentation to use while logging
:return: True on success (currently ignored)
"""
# Maps have their content in their annotations
for cd, annotations in self.annotations.items():
# Annotations are associated to their definition class
if cd.name == "java.util.HashMap":
# We are in the annotation created by the handled class
# Group annotation elements 2 by 2
# (storage is: key, value, key, value, ...)
args = [iter(annotations[1:])] * 2
for key, value in zip(*args):
self[key] = value
# Job done
return True
# Couldn't load the data
return False
class MapObjectTransformer(javaobj.v2.api.ObjectTransformer):
"""
Creates a JavaInstance object with custom loading methods for the
classes it can handle
"""
def create_instance(self, classdesc):
# type: (JavaClassDesc) -> Optional[JavaInstance]
"""
Transforms a parsed Java object into a Python object
:param classdesc: The description of a Java class
:return: The Python form of the object, or the original JavaObject
"""
if classdesc.name == "java.util.HashMap":
# We can handle this class description
return JavaMap()
else:
# Return None if the class is not handled
return None
Custom Object TransformerThe custom transformer is called when the class is not handled by the default
object transformer.
A custom object transformer still inherits from the The sample given here is used in the unit tests. Java sampleOn the Java side, we create various classes and write them as we wish: class CustomClass implements Serializable {
private static final long serialVersionUID = 1;
public void start(ObjectOutputStream out) throws Exception {
this.writeObject(out);
}
private void writeObject(ObjectOutputStream out) throws IOException {
CustomWriter custom = new CustomWriter(42);
out.writeObject(custom);
out.flush();
}
}
class RandomChild extends Random {
private static final long serialVersionUID = 1;
private int num = 1;
private double doub = 4.5;
RandomChild(int seed) {
super(seed);
}
}
class CustomWriter implements Serializable {
protected RandomChild custom_obj;
CustomWriter(int seed) {
custom_obj = new RandomChild(seed);
}
private static final long serialVersionUID = 1;
private static final int CURRENT_SERIAL_VERSION = 0;
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeInt(CURRENT_SERIAL_VERSION);
out.writeObject(custom_obj);
}
}
An here is a sample writing of that kind of object: ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("custom_objects.ser"));
CustomClass writer = new CustomClass();
writer.start(oos);
oos.flush();
oos.close();
Python sampleOn the Python side, the first step is to define the custom transformers.
They are children of the class BaseTransformer(javaobj.v2.transformers.ObjectTransformer):
"""
Creates a JavaInstance object with custom loading methods for the
classes it can handle
"""
def __init__(self, handled_classes=None):
self.instance = None
self.handled_classes = handled_classes or {}
def create_instance(self, classdesc):
"""
Transforms a parsed Java object into a Python object
:param classdesc: The description of a Java class
:return: The Python form of the object, or the original JavaObject
"""
if classdesc.name in self.handled_classes:
self.instance = self.handled_classes[classdesc.name]()
return self.instance
return None
class RandomChildTransformer(BaseTransformer):
def __init__(self):
super(RandomChildTransformer, self).__init__(
{"RandomChild": RandomChildInstance}
)
class CustomWriterTransformer(BaseTransformer):
def __init__(self):
super(CustomWriterTransformer, self).__init__(
{"CustomWriter": CustomWriterInstance}
)
class JavaRandomTransformer(BaseTransformer):
def __init__(self):
super(JavaRandomTransformer, self).__init__()
self.name = "java.util.Random"
self.field_names = ["haveNextNextGaussian", "nextNextGaussian", "seed"]
self.field_types = [
javaobj.v2.beans.FieldType.BOOLEAN,
javaobj.v2.beans.FieldType.DOUBLE,
javaobj.v2.beans.FieldType.LONG,
]
def load_custom_writeObject(self, parser, reader, name):
if name != self.name:
return None
fields = []
values = []
for f_name, f_type in zip(self.field_names, self.field_types):
values.append(parser._read_field_value(f_type))
fields.append(javaobj.v2.beans.JavaField(f_type, f_name))
class_desc = javaobj.v2.beans.JavaClassDesc(
javaobj.v2.beans.ClassDescType.NORMALCLASS
)
class_desc.name = self.name
class_desc.desc_flags = javaobj.v2.beans.ClassDataType.EXTERNAL_CONTENTS
class_desc.fields = fields
class_desc.field_data = values
return class_desc
Second step is defining the representation of the instances, where the real
object loading occurs. Those classes inherit from
class CustomWriterInstance(javaobj.v2.beans.JavaInstance):
def __init__(self):
javaobj.v2.beans.JavaInstance.__init__(self)
def load_from_instance(self):
"""
Updates the content of this instance
from its parsed fields and annotations
:return: True on success, False on error
"""
if self.classdesc and self.classdesc in self.annotations:
# Here, we known there is something written before the fields,
# even if it's not declared in the class description
fields = ["int_not_in_fields"] + self.classdesc.fields_names
raw_data = self.annotations[self.classdesc]
int_not_in_fields = struct.unpack(
">i", BytesIO(raw_data[0].data).read(4)
)[0]
custom_obj = raw_data[1]
values = [int_not_in_fields, custom_obj]
self.field_data = dict(zip(fields, values))
return True
return False
class RandomChildInstance(javaobj.v2.beans.JavaInstance):
def load_from_instance(self):
"""
Updates the content of this instance
from its parsed fields and annotations
:return: True on success, False on error
"""
if self.classdesc and self.classdesc in self.field_data:
fields = self.classdesc.fields_names
values = [
self.field_data[self.classdesc][self.classdesc.fields[i]]
for i in range(len(fields))
]
self.field_data = dict(zip(fields, values))
if (
self.classdesc.super_class
and self.classdesc.super_class in self.annotations
):
super_class = self.annotations[self.classdesc.super_class][0]
self.annotations = dict(
zip(super_class.fields_names, super_class.field_data)
)
return True
return False
Finally we can use the transformers in the loading process.
Note that even if it is not explicitly given, the # Load the object using those transformers
transformers = [
CustomWriterTransformer(),
RandomChildTransformer(),
JavaRandomTransformer()
]
with open("custom_objects.ser", "rb") as fd:
pobj = javaobj.load(fd, *transformers)
# Here we show a field that isn't visible from the class description
# The field belongs to the class but it's not serialized by default because
# it's static. See: https://stackoverflow.com/a/16477421/12621168
print(pobj.field_data["int_not_in_fields"])
Usage (V3 implementation)
The
Sample usage: import javaobj.v3 as javaobj
with open("obj5.ser", "rb") as fd:
pobj = javaobj.load(fd)
# Access fields by name (preferred)
value = pobj.get_field("myField")
# Or use attribute-style access (issues a warning on ambiguity)
value = pobj.myField
Automatic type conversion (V3)
Any other class falls back to a generic New features in V3
Security limits
import javaobj.v3 as javaobj
with open("untrusted.ser", "rb") as fd:
pobj = javaobj.load(
fd,
max_array_size=10 * 1024 * 1024, # 10 MiB max per array
max_depth=100, # max object-graph depth
)
Error handling (V3)
import javaobj.v3 as javaobj
from javaobj.v3.exceptions import JavaObjError, ParseError, SecurityError
with open("obj5.ser", "rb") as fd:
try:
pobj = javaobj.load(fd)
except SecurityError:
# A max_depth or max_array_size limit was exceeded
...
except ParseError as e:
# The stream does not follow the protocol; e.offset is the byte
# offset in the stream where the error occurred, or -1 if unknown
print(e, "at offset", e.offset)
except JavaObjError:
# Catch-all base class for everything else javaobj.v3 raises
...
Object Transformer V3The
The Using NumPy arrays (V3)import javaobj.v3 as javaobj
with open("arrays.ser", "rb") as fd:
pobj = javaobj.load(fd, use_numpy_arrays=True)
When Marshalling / Writing (V3)The
Both functions accept any combination of
Simple round-tripimport javaobj.v3 as javaobj
# Parse an existing file
with open("obj5.ser", "rb") as fd:
pobj = javaobj.load(fd)
# Serialize back to bytes
data = javaobj.dumps(pobj)
# Or write directly to a file
with open("obj5_copy.ser", "wb") as fd:
javaobj.dump(fd, pobj)
Writing multiple objectsimport javaobj.v3 as javaobj
from javaobj.v3.beans import JavaString
with open("a.ser", "rb") as fd:
obj_a = javaobj.load(fd)
# Write two objects into one stream
data = javaobj.dumps(obj_a, JavaString("hello"))
# Re-parse: returns a list when the stream holds more than one object
result = javaobj.loads(data) # -> [obj_a, JavaString("hello")]
Supported constructs
Building a Java object from scratchYou can construct the v3 beans manually to serialize a Python object as if it were a Java one. The key types are:
All beans accept import javaobj.v3 as javaobj
from javaobj.constants import ClassDescFlags
from javaobj.v3.beans import (
FieldType,
JavaClassDesc,
ClassDescType,
JavaField,
JavaInstance,
JavaString,
)
# ── 1. Describe the Java class ────────────────────────────────────────────────
#
# Java equivalent:
#
# package com.example;
# public class Point implements java.io.Serializable {
# private static final long serialVersionUID = 1L;
# public int x;
# public int y;
# }
field_x = JavaField(type=FieldType.INTEGER, name="x")
field_y = JavaField(type=FieldType.INTEGER, name="y")
point_cd = JavaClassDesc(
handle=0, # assigned by the writer
name="com.example.Point",
serial_version_uid=1,
desc_flags=ClassDescFlags.SC_SERIALIZABLE,
fields=[field_x, field_y],
)
# ── 2. Create an instance ─────────────────────────────────────────────────────
point = JavaInstance(
handle=0,
classdesc=point_cd,
field_data={
point_cd: {
field_x: 42,
field_y: -7,
}
},
)
# ── 3. Serialize ──────────────────────────────────────────────────────────────
data = javaobj.dumps(point)
# ── 4. Round-trip check ───────────────────────────────────────────────────────
restored = javaobj.loads(data)
print(restored.get_field("x")) # 42
print(restored.get_field("y")) # -7
For object-type fields (e.g. a field_name = JavaField(
type=FieldType.OBJECT,
name="name",
class_name="Ljava/lang/String;", # binary name for java.lang.String
)
person_cd = JavaClassDesc(
handle=0,
name="com.example.Person",
serial_version_uid=1,
desc_flags=ClassDescFlags.SC_SERIALIZABLE,
fields=[field_name, field_x], # reuse field_x from above
)
alice = JavaInstance(
handle=0,
classdesc=person_cd,
field_data={
person_cd: {
field_name: JavaString(handle=0, value="Alice"),
field_x: 30,
}
},
)
data = javaobj.dumps(alice)
Logging (V3)The parser and the writer log through the standard import logging
logging.getLogger("javaobj.v3").setLevel(logging.DEBUG)
Migration to V3From V1 to V3
Shallow conversion helper (best-effort, for gradual migration): from javaobj.v3._compat import v1_to_v3
v3_obj = v1_to_v3(v1_obj)
From V2 to V3
Shallow conversion helper (best-effort, for gradual migration): from javaobj.v3._compat import v2_to_v3
v3_obj = v2_to_v3(v2_obj)
Project linksData verified by PyPI on Aug 12, 2026
Data provided by the project maintainers, verified at the time the release was uploaded to PyPI.
Key datesPyPI dataData sourced directly from PyPI's database.
1 maintainerPyPI dataData sourced directly from PyPI's database.
CreditsAuthor: Volodymyr Buell Maintainer: Thomas Calmant GitHub StatisticsData verified by PyPI on Aug 12, 2026The GitHub source repository was provided by the project maintainers and verified by PyPI at the time of upload. Stars, forks, and open issues/PRs are derived from that repository and have not been independently verified.
ProvenanceData verified by PyPI on Aug 12, 2026Data provided by the project maintainers and verified by PyPI at the time of upload.
License expression
Apache-2.0
RequiresPython !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, >=2.7 Provides Extra
Tags
Classifiers
MetadataProject linksData verified by PyPI on Aug 12, 2026
Data provided by the project maintainers, verified at the time the release was uploaded to PyPI.
Key datesPyPI dataData sourced directly from PyPI's database.
1 maintainerPyPI dataData sourced directly from PyPI's database.
CreditsAuthor: Volodymyr Buell Maintainer: Thomas Calmant GitHub StatisticsData verified by PyPI on Aug 12, 2026The GitHub source repository was provided by the project maintainers and verified by PyPI at the time of upload. Stars, forks, and open issues/PRs are derived from that repository and have not been independently verified.
ProvenanceData verified by PyPI on Aug 12, 2026Data provided by the project maintainers and verified by PyPI at the time of upload.
License expression
Apache-2.0
RequiresPython !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, >=2.7 Provides Extra
Tags
Classifiers
Release files for javaobj-py3 0.6.1For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation. Source distribution (sdist)
Built distribution (wheel)
Total release size: 208.5 kB Release files / javaobj_py3-0.6.1.tar.gz
ProvenanceProvenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats. PyPI Publish AttestationPyPI verified that this artifact, at this checksum, originated from the publisher listed below. Signed by GitHub Actions, verified by PyPI on Aug 12, 2026. Transparency logIdentity
WorkflowArtifact
Release files / javaobj_py3-0.6.1-py2.py3-none-any.whl
ProvenanceProvenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats. PyPI Publish AttestationPyPI verified that this artifact, at this checksum, originated from the publisher listed below. Signed by GitHub Actions, verified by PyPI on Aug 12, 2026. Transparency logIdentity
WorkflowArtifact
Security for javaobj-py3 0.6.1ProvenanceProvenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats. Full provenanceBoth files in this release have been uploaded with provenance metadata.
Select from 2 files
No files match the current filters. Reset filters
Attestation for javaobj_py3-0.6.1.tar.gzPyPI Publish AttestationPyPI verified that this artifact, at this checksum, originated from the publisher listed below. Signed by GitHub Actions, verified by PyPI on Aug 12, 2026. Transparency logIdentity
WorkflowArtifact
Attestation for javaobj_py3-0.6.1-py2.py3-none-any.whlPyPI Publish AttestationPyPI verified that this artifact, at this checksum, originated from the publisher listed below. Signed by GitHub Actions, verified by PyPI on Aug 12, 2026. Transparency logIdentity
WorkflowArtifact
A note on package securityPyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package. To learn more about protecting yourself from malicious actors, visit our package security documentation. Release history Release notifications | RSS feed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |