This module provides functions for encoding and decoding a lightweight text-based format for serializing the object types supported by UL4.
It is extensible to allow encoding/decoding arbitrary instances (i.e. it is
basically a reimplementation of pickle
, but with string input/output
instead of bytes and with an eye towards cross-plattform support).
There are implementations for Python (this module), Java and Javascript (as part of the UL4 packages for those languages).
Furthermore there's an Oracle package that can be used for generating UL4on encoded data.
Basic usage follows the API design of pickle
, json
, etc. and
supports most builtin Python types:
>>> from ll import ul4on >>> ul4on.dumps(None) 'n' >>> ul4on.loads('n') >>> ul4on.dumps(False) 'bF' >>> ul4on.loads('bF') False >>> ul4on.dumps(42) 'i42' >>> ul4on.loads('i42') 42 >>> ul4on.dumps(42.5) 'f42.5' >>> ul4on.loads('f42.5') 42.5 >>> ul4on.dumps('foo') "S'foo'" >>> ul4on.loads("S'foo'") 'foo'
datetime
and timedelta
objects are supported too:
>>> import datetime >>> ul4on.dumps(datetime.datetime.now()) 'Z i2014 i11 i3 i18 i16 i45 i314157' >>> ul4on.loads('Z i2014 i11 i3 i18 i16 i45 i314157') datetime.datetime(2014, 11, 3, 18, 16, 45, 314157) >>> ul4on.dumps(datetime.timedelta(days=1)) 'T i1 i0 i0' >>> ul4on.loads('T i1 i0 i0') datetime.timedelta(1)
ll.ul4on
also supports Color
objects from ll.color
:
>>> from ll import color >>> ul4on.dumps(color.red) 'C i255 i0 i0 i255' >>> ul4on.loads('C i255 i0 i0 i255') Color(0xff, 0x00, 0x00)
Lists, dictionaries and sets are also supported:
>>> ul4on.dumps([1, 2, 3]) 'L i1 i2 i3 ]' >>> ul4on.loads('L i1 i2 i3 ]') [1, 2, 3] >>> ul4on.dumps(dict(one=1, two=2)) "D S'two' i2 S'one' i1 }" >>> ul4on.loads("D S'two' i2 S'one' i1 }") {'one': 1, 'two': 2} >>> ul4on.dumps({1, 2, 3}) 'Y i1 i2 i3 }' >>> ul4on.loads('Y i1 i2 i3 }') {1, 2, 3}
ll.ul4on
can also handle recursive data structures:
>>> r = [] >>> r.append(r) >>> ul4on.dumps(r) 'L ^0 ]' >>> r2 = ul4on.loads('L ^0 ]') >>> r2 [[...]] >>> r2 is r2[0] True >>> r = {} >>> r['recursive'] = r >>> ul4on.dumps(r) "D S'recursive' ^0 }" >>> r2 = ul4on.loads("D S'recursive' ^0 }") >>> r2 {'recursive': {...}} >>> r2['recursive'] is r2 True
UL4ON is extensible. It supports serializing arbitrary instances by registering the class with the UL4ON serialization machinery:
from ll import ul4on @ul4on.register("com.example.person") class Person: def __init__(self, firstname=None, lastname=None): self.firstname = firstname self.lastname = lastname def __repr__(self): return "<Person firstname={!r} lastname={!r}>".format(self.firstname, self.lastname) def ul4ondump(self, encoder): encoder.dump(self.firstname) encoder.dump(self.lastname) def ul4onload(self, decoder): self.firstname = decoder.load() self.lastname = decoder.load() jd = Person("John", "Doe") output = ul4on.dumps(jd) print("Dump:", output) jd2 = ul4on.loads(output) print("Loaded:", jd2)
This script outputs:
Dump: O S'com.example.person' S'John' S'Doe' ) Loaded: <Person firstname='John' lastname='Doe'>
def register
(name
):
This decorator can be used to register the decorated class with the
ll.ul4on
serialization machinery.
name
must be a globally unique name for the class. To avoid
name collisions Java's class naming system should be used (i.e. an
inverted domain name like com.example.foo.bar
).
name
will be stored in the class attribute ul4onname
.
class Encoder
(object
):
def __init__
(self
, stream
, indent
=None
):
Create an encoder for serializing objects to self.stream
.
stream
must provide a write
method.
def _record
(self
, obj
):
def _line
(self
, line
, *items
):
def dump
(self
, obj
):
Serialize obj
as an UL4ON formatted stream.
class Decoder
(object
):
def __init__
(self
, stream
):
Create a decoder for deserializing objects from self.stream
.
stream
must provide a read
method.
def load
(self
):
Deserialize the next object in the stream and return it.
def _readint
(self
):
def _loading
(self
, obj
):
def _nextchar
(self
, nextchar
=None
):
def _beginfakeloading
(self
):
def _endfakeloading
(self
, oldpos
, value
):
def _load
(self
, typecode
):
class StreamBuffer
(object
):
def __init__
(self
, stream
, bufsize
=1048576
):
def read
(self
, size
):
def dumps
(obj
, indent
=None
):
Serialize obj
as an UL4ON formatted string.
def dump
(obj
, stream
, indent
=None
):
Serialize obj
as an UL4ON formatted stream to stream
.
stream
must provide a write
method.
def loadclob
(clob
, bufsize
=1048576
):
Deserialize clob
(which must be an cx_Oracle
CLOB
variable
containing an UL4ON formatted object) to a Python object.
bufsize
specifies the chunk size for reading the underlying CLOB
object.
def loads
(string
):
Deserialize string
(which must be a string containing an UL4ON
formatted object) to a Python object.
def load
(stream
):
Deserialize stream
(which must be file-like object with a read
method containing an UL4ON formatted object) to a Python object.