0

I've been working on a small project for myself, where I use riak, python and flask framework. Like in most cases, I'd like to store creation date of my objects stored in riak, and some other dates as well (like session expiration dates). When I first tried to just store date object, I've ecountered an error, to which the solution was to use a code like this:

def date(obj):
    return obj.isoformat() if hasattr(obj, 'isoformat') else obj


def json_date():
    return json.dumps(datetime.now(), default=date)

I've tested it, and happily used it, but later on I've ecountered some more complex needs, namely session expiration date in N minutes from now, so I've quickly wrote somethin like that:

def json_session_expiration_date():
    return json.dumps(datetime.now() + timedelta(minutes=15), default=date)

Now that I've core of my application working, I wanted to clean up stupid and suboptimal code, before I move to writing more features, and one issue I have is with these three functions - I dont clearly understand what's the objective of the date(obj) function, and therefore I cant join them all in one function easily. Any advice is appreciated!

SpankMe
  • 836
  • 1
  • 8
  • 23

2 Answers2

1

The date function is used as the default function for the dumps function; the function is called for any type that JSON doesn't know how to handle.

The JSON standard only knows about numbers, strings, booleans, nulls (None in python), objects (dicts in python) and lists. If you want to handle anything outside of that limited set of types, you need to express that 'something' in terms of those types.

The default() is used for that purpose; it is called for any object that cannot be serialized to JSON as-is. A datetime object is one such type. When you a datetime object to json.dumps(), the default function will be asked to create a serializable version of it.

Note that returning obj is not the correct way to handle types you don't know how to convert. Raise TypeError instead:

def date(obj):
    try:
        return obj.isoformat()
    except AttributeError:
        raise TypeError()
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Ok, that's an explanation for the question about data() function, but is it *the* way to handle date data with python and riak, or is there a more elegant, robust and clean solution? – SpankMe Jan 22 '13 at 19:58
  • @SpankMe: Pyramid handles JSON through [custom serialization hooks](http://pyramid.readthedocs.org/en/latest/narr/renderers.html#json-serializing-custom-objects), but under the hood it still uses `dumps(..., default=handler)` for that. See the [source code for the `default` function](https://github.com/Pylons/pyramid/blob/master/pyramid/renderers.py#L264). – Martijn Pieters Jan 22 '13 at 21:08
1

Using date.isoformat() will return ISO8601 formatted date strings, which is the way to handle dates in Riak. The date string can then be converted back into a Date object in javascript during map/reduce, or simply sorted as a string in a reduce phase.

If you're using the default parameter of json.dumps() you should certainly follow Martijn Pieters example and raise a TypeError if the object doesn't have the isoformat() property - which only the Date and DateTime objects will have.

mafrosis
  • 2,720
  • 1
  • 25
  • 34