Skip to main content

Custom datatypes (like datetime) serialization to/from JSON.

Project description

https://img.shields.io/pypi/v/jsonplus.svg https://img.shields.io/pypi/l/jsonplus.svg https://img.shields.io/pypi/wheel/jsonplus.svg https://img.shields.io/pypi/pyversions/jsonplus.svg https://api.travis-ci.org/randomir/jsonplus.svg?branch=master

Serialization of Python types to JSON that “just works”.

Forget errors like:

TypeError: datetime.datetime(...) is not JSON serializable

In addition to (de-)serialization of basic types (provided by simplejson), jsonplus provides support for exact (de-)serialization of other commonly used types, like: tuple/namedtuple, set/frozenset, complex/decimal.Decimal/fractions.Fraction, and datetime/date/time/timedelta.

If the exact representation of types is not your cup of tea, and all you wish for is the json.dumps to work on your data structure with non-basic types, accepting the loss of “type-precision” along the way, than you can use the compatibility mode (thread-local jsonplus.prefer_compat(), or per-call override jsonplus.dumps(..., exact=False)).

Installation

jsonplus is available as a Python package. To install it, simply type:

$ pip install jsonplus

Usage

You can treat jsonplus as a friendly drop-in replacement for json/simplejson.

>>> import jsonplus as json

>>> x = json.loads('{"a":1,"b":2}')
>>> y = json.dumps(x, indent=4)
>>> z = json.pretty(x)

Examples

Let’s start with that beloved datetime.

>>> import jsonplus as json

>>> from datetime import datetime
>>> json.dumps({
...     "x": [4,3],
...     "t": datetime.now()
... })
'{"x":[4,3],"t":{"__class__":"datetime","__value__":"2013-09-06T23:38:55.819791"}}'

>>> json.loads(_)
{u'x': [4, 3], u't': datetime.datetime(2013, 9, 6, 23, 38, 55, 819791)}

Similarly for other datetime.* types, like timedelta, date, and time:

>>> from datetime import timedelta, date, time
>>> print(json.pretty({"dt": timedelta(0, 1234567, 123), "d": date.today(), "t": datetime.now().time()}))
{
    "d": {
        "__class__": "date",
        "__value__": "2013-09-22"
    },
    "dt": {
        "__class__": "timedelta",
        "__value__": {
            "days": 14,
            "microseconds": 123,
            "seconds": 24967
        }
    },
    "t": {
        "__class__": "time",
        "__value__": "23:33:16.335360"
    }
}

Also, set and complex:

>>> json.dumps([set(range(3)), 1+2j])
'[{"__class__":"set","__value__":[0,1,2]},{"__class__":"complex","__value__":{"real":1.0,"imag":2.0}}]'

>>> json.loads(_)
[set([0, 1, 2]), (1+2j)]

tuple and namedtuple are also preserved:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])

>>> data = json.pretty({"vect": (1, 2, 3), "dot": Point(3, 4)})
>>> print(data)
{
    "dot": {
        "__class__": "namedtuple",
        "__value__": {
            "fields": [
                "x",
                "y"
            ],
            "name": "Point",
            "values": [
                3,
                4
            ]
        }
    },
    "vect": {
        "__class__": "tuple",
        "__value__": [
            1,
            2,
            3
        ]
    }
}

>>> json.loads(data)
{'vect': (1, 2, 3), 'dot': Point(x=3, y=4)}

Compatibility mode

All types supported in the exact mode are also supported in the compatibility mode. JSON representation differs, however.

In the exact mode, type and value are encoded with JSON Object’s __class__ and __value__ keys, while in the compatibility mode, values are “rounded off” to the closest JSON type.

For example, tuple and set are represented with JSON Array, and namedtuple is coded as a plain JSON Object. Decimal is represented as JSON Number with arbitrary precision (which is lost if decoded as float).

To switch between the exact and compatibility modes, use the (thread-local) functions prefer_exact() and prefer_compat(), or call dumps(..., exact=False):

>>> import jsonplus as json

>>> json.prefer_compat()
# or:
>>> json.prefer(json.COMPAT)
# per-instance override:
>>> json.dumps(obj, exact=False)

# to go back to (default) exact coding:
>>> json.prefer_exact()

The above tuple/namedtuple/datetime examples run in the compatibility coding mode result with:

>>> json.prefer_compat()

>>> print(json.pretty({"vect": (1, 2, 3), "dot": Point(3, 4)}))
{
    "point": {
        "x": 3,
        "y": 4
    },
    "vector": [
        1,
        2,
        3
    ]
}

>>> json.dumps({"now": datetime.now()})
'{"now":"2017-01-26T00:37:40.293963"}'

So, to be able to properly decode values in the compatibility mode, some additional context will have to be provided to the decoder.

Adding user types

Support for user/custom types can easily be added with @jsonplus.encoder and @jsonplus.decoder decorators.

For example, to enable serialization of your type named mytype in exact mode (to add compat-mode serialization, append exact=False in decorator):

@jsonplus.encoder('mytype')
def mytype_exact_encoder(myobj):
    return myobj.to_json()
@jsonplus.decoder('mytype')
def mytype_decoder(value):
    return mytype(value, reconstruct=True, ...)

If detection of object class is more complex than a simple classname comparison, if you need to use a predicate function, simply add predicate=... to the encoder decorator. For example:

@jsonplus.encoder('BaseClass', lambda obj: isinstance(obj, BaseClass))
def all_derived_classes_encoder(derived):
    return derived.base_encoder()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jsonplus-0.8.0.tar.gz (9.2 kB view details)

Uploaded Source

Built Distribution

jsonplus-0.8.0-py2.py3-none-any.whl (11.5 kB view details)

Uploaded Python 2Python 3

File details

Details for the file jsonplus-0.8.0.tar.gz.

File metadata

  • Download URL: jsonplus-0.8.0.tar.gz
  • Upload date:
  • Size: 9.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for jsonplus-0.8.0.tar.gz
Algorithm Hash digest
SHA256 01d35765b6611f9ee403bd8e858cf089c409c524227cab9356fc8f80781bdb17
MD5 6fc314fc9a9490ef5e6207274da3be74
BLAKE2b-256 94868f46b10cb69b9594f212a50df01e3c777771420a2ffd0dfa8fca369297ee

See more details on using hashes here.

File details

Details for the file jsonplus-0.8.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for jsonplus-0.8.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 bb98d8e4e785af8dbcf98111b4eb2cd88f0adbe48d0c629f899eabd07b24f0cd
MD5 eb6f268390ac6505653074eb746ae1ad
BLAKE2b-256 d60a0438f4131477fa827431137eec9c4bd11e7884065e5812dc989c80d91e82

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page