{"componentChunkName":"component---src-templates-post-tsx","path":"/posts/2019/09/custom-json/","result":{"data":{"markdownRemark":{"fields":{"slug":"/2019/09/custom-json/"},"frontmatter":{"title":"Customizing JSON parser and stringifier","tag":["json","python","javascript"],"image":"https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQ7pdGqnbQneek9mD0QbbdEFO1kjNHxeG2jRt42OoCY2a9HefQy"},"correctedDateEpoch":1568134800000,"html":"<p>I have always wanted <code>JSON.parse</code> and <code>JSON.stringify</code> to deal with custom objects, such as <code>Date</code> and <code>Set</code>.</p>\n<p>BTW, I have successfully done so in two languages, Python and JavaScript (TypeScript).</p>\n<!-- excerpt_separator -->\n<p>In Python, you have to override <code>default</code> and <code>object_hook</code> for <code>json.dumps</code> and <code>json.loads</code> respectively.</p>\n<pre><code class=\"language-python\">import json\nfrom datetime import datetime\n\n\ndef default(obj):\n    if isinstance(obj, datetime):\n        return str(obj)\n\n    raise TypeError\n\n\nclass ComplexEncoder(json.JSONEncoder):\n    def default(self, obj):\n        try:\n            return default(obj)\n        except TypeError:\n            return super().default(self, obj)\n\n\ndef object_hook(d):\n    date_formats = [\n        \"%Y-%m-%d %H:%M:%S.%f\"\n    ]\n\n    for k, v in d.items():\n        if isinstance(v, str):\n            for f in date_formats:\n                try:\n                    d[k] = datetime.strptime(v, f)\n                    break\n                except ValueError:\n                    pass\n\n    return d\n\n\nif __name__ == \"__main__\":\n    print(json.dumps(datetime.now(), cls=ComplexEncoder))\n    print(json.dumps(datetime.now(), default=default))\n    print(json.loads(json.dumps({\"a\": datetime.now()}, default=default), object_hook=object_hook))\n</code></pre>\n<p>For JavaScript, there is <code>Object.prototype.toJSON</code> and <code>reviver</code>. You can override both, like this,</p>\n<pre><code class=\"language-typescript\">Date.prototype.toJSON = function() {\n  return this.toISOString();\n};\n\nfunction reviver(key: string, value: any) {\n  if (typeof value === \"string\") {\n    if (/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d+\\S+$/.test(value)) {\n      return new Date(value)\n    }\n  }\n  return value;\n}\n\nconsole.log(JSON.stringify(new Date()));\nconsole.log(JSON.parse(JSON.stringify(new Date()), reviver));\n</code></pre>\n<p>Indeed, if you want to handle Python's <code>datetime</code> string, you might need <a href=\"https://momentjs.com/\">moment.js</a> library.</p>"}},"pageContext":{"slug":"/2019/09/custom-json/"}}}