rejson-py is a package that allows storing, updating and querying objects as JSON documents in a Redis database that is extended with the ReJSON module. The package extends redis-py's interface with ReJSON's API, and performs on-the-fly serialization/deserialization of objects to/from JSON.
$ pip install rejson
from rejson import Client, Path
rj = Client(host='localhost', port=6379)
# Set the key `obj` to some object
obj = {
'answer': 42,
'arr': [None, True, 3.14],
'truth': {
'coord': 'out there'
}
}
rj.jsonset('obj', Path.rootPath(), obj)
# Get something
print 'Is there anybody... {}?'.format(
rj.jsonget('obj', Path('.truth.coord'))
)
# Delete something (or perhaps nothing), append something and pop it
rj.jsondel('obj', Path('.arr[0]'))
rj.jsonarrappend('obj', Path('.arr'), 'something')
print '{} popped!'.format(rj.jsonarrpop('obj', Path('.arr')))
# Update something else
rj.jsonset('obj', Path('.answer'), 2.17)
# And use just like the regular redis-py client
jp = rj.pipeline()
jp.set('foo', 'bar')
jp.jsonset('baz', Path.rootPath(), 'qaz')
jp.execute()
rejson-py uses Python's json
.
The client can be set to use custom encoders/decoders at creation, or by calling
explicitly the setEncoder()
and
setDecoder()
methods, respectively.
The following shows how to use this for a custom class that's stored as a JSON string for example:
from json import JSONEncoder, JSONDecoder
from rejson import Client
class CustomClass(object):
"Some non-JSON-serializable"
def __init__(self, s=None):
if s is not None:
# deserialize the instance from the serialization
if s.startswith('CustomClass:'):
...
else:
raise Exception('unknown format')
else:
# initialize the instance
...
def __str__(self):
_str = 'CustomClass:'
# append the instance's state to the serialization
...
return _str
...
class CustomEncoder(JSONEncoder):
"A custom encoder for the custom class"
def default(self, obj):
if isinstance(obj, CustomClass):
return str(obj)
return json.JSONEncoder.encode(self, obj)
class TestDecoder(JSONDecoder):
"A custom decoder for the custom class"
def decode(self, obj):
d = json.JSONDecoder.decode(self, obj)
if isinstance(d, basestring) and d.startswith('CustomClass:'):
return CustomClass(d)
return d
# Create a new instance of CustomClass
obj = CustomClass()
# Create a new client with the custom encoder and decoder
rj = Client(encoder=CustomEncoder(), decoder=CustomDecoder())
# Store the object
rj.jsonset('custom', Path.rootPath(), obj))
# Retrieve it
obj = rj.jsonget('custom', Path.rootPath())
This class subclasses redis-py's StrictRedis
and implements ReJSON's
commmands (prefixed with "json").
The client performs on-the-fly serialization/deserialization of objects to/from JSON, and provides the ability to use a custom encoder/decoder.
def __init__(self, encoder=None, decoder=None, *args, **kwargs)
Creates a new ReJSON client.
encoder
should be an instance of a json.JSONEncoder
class
decoder
should be an instance of a json.JSONDecoder
class
def jsonarrappend(self, name, path='.', *args)
Appends the objects args
to the array under the path` in key
name``
def jsonarrindex(self, name, path, scalar, start=0, stop=-1)
Returns the index of scalar
in the JSON array under path
at key
name
. The search can be limited using the optional inclusive
start
and exclusive stop
indices.
def jsonarrinsert(self, name, path, index, *args)
Inserts the objects args
to the array at index index
under the
path` in key
name``
def jsonarrlen(self, name, path='.')
Returns the length of the array JSON value under path
at key
name
def jsonarrpop(self, name, path='.', index=-1)
Pops the element at index
in the array JSON value under path
at
key name
def jsonarrtrim(self, name, path, start, stop)
Trim the array JSON value under path
at key name
to the
inclusive range given by start
and stop
def jsondel(self, name, path='.')
Deletes the JSON value stored at key name
under path
def jsonget(self, name, *args)
Get the object stored as a JSON value at key name
args
is zero or more paths, and defaults to root path
def jsonmget(self, path, *args)
Gets the objects stored as a JSON values under path
from
keys args
def jsonnumincrby(self, name, path, number)
Increments the numeric (integer or floating point) JSON value under
path
at key name
by the provided number
def jsonnummultby(self, name, path, number)
Multiplies the numeric (integer or floating point) JSON value under
path
at key name
with the provided number
def jsonobjkeys(self, name, path='.')
Returns the key names in the dictionary JSON value under path
at key
name
def jsonobjlen(self, name, path='.')
Returns the length of the dictionary JSON value under path
at key
name
def jsonset(self, name, path, obj, nx=False, xx=False)
Set the JSON value at key name
under the path
to obj
nx
if set to True, set value
only if it does not exist
xx
if set to True, set value
only if it exists
def jsonstrappend(self, name, string, path='.')
Appends to the string JSON value under path
at key name
the
provided string
def jsonstrlen(self, name, path='.')
Returns the length of the string JSON value under path
at key
name
def jsontype(self, name, path='.')
Gets the type of the JSON value under path
from key name
def setDecoder(self, decoder)
Sets the client's decoder
decoder
should be an instance of a json.JSONDecoder
class
def setEncoder(self, encoder)
Sets the client's encoder
encoder
should be an instance of a json.JSONEncoder
class
This class represents a path in a JSON value
def __init__(self, path)
Make a new path based on the string representation in path