|
30 | 30 | import uuid |
31 | 31 | import inspect |
32 | 32 |
|
| 33 | +from datetime import datetime |
| 34 | + |
33 | 35 | from cloudant.document import Document |
34 | 36 | from cloudant.error import CloudantDocumentException |
35 | 37 |
|
@@ -859,5 +861,47 @@ def test_document_request_fails_after_client_disconnects(self): |
859 | 861 | finally: |
860 | 862 | self.client.connect() |
861 | 863 |
|
| 864 | + def test_document_custom_json_encoder_and_decoder(self): |
| 865 | + dt_format = '%Y-%m-%dT%H:%M:%S' |
| 866 | + |
| 867 | + class DTEncoder(json.JSONEncoder): |
| 868 | + |
| 869 | + def default(self, obj): |
| 870 | + if isinstance(obj, datetime): |
| 871 | + return { |
| 872 | + '_type': 'datetime', |
| 873 | + 'value': obj.strftime(dt_format) |
| 874 | + } |
| 875 | + return super(DTEncoder, self).default(obj) |
| 876 | + |
| 877 | + class DTDecoder(json.JSONDecoder): |
| 878 | + |
| 879 | + def __init__(self, *args, **kwargs): |
| 880 | + json.JSONDecoder.__init__(self, object_hook=self.object_hook, |
| 881 | + *args, **kwargs) |
| 882 | + |
| 883 | + def object_hook(self, obj): |
| 884 | + if '_type' not in obj: |
| 885 | + return obj |
| 886 | + if obj['_type'] == 'datetime': |
| 887 | + return datetime.strptime(obj['value'], dt_format) |
| 888 | + return obj |
| 889 | + |
| 890 | + doc = Document(self.db, encoder=DTEncoder) |
| 891 | + doc['name'] = 'julia' |
| 892 | + doc['dt'] = datetime(2018, 7, 9, 15, 11, 10, 0) |
| 893 | + doc.save() |
| 894 | + |
| 895 | + raw_doc = self.db.all_docs(include_docs=True)['rows'][0]['doc'] |
| 896 | + |
| 897 | + self.assertEquals(raw_doc['name'], 'julia') |
| 898 | + self.assertEquals(raw_doc['dt']['_type'], 'datetime') |
| 899 | + self.assertEquals(raw_doc['dt']['value'], '2018-07-09T15:11:10') |
| 900 | + |
| 901 | + doc2 = Document(self.db, doc['_id'], decoder=DTDecoder) |
| 902 | + doc2.fetch() |
| 903 | + |
| 904 | + self.assertEquals(doc2['dt'], doc['dt']) |
| 905 | + |
862 | 906 | if __name__ == '__main__': |
863 | 907 | unittest.main() |
0 commit comments