Skip to content

Instantly share code, notes, and snippets.

@poppe1219
Last active August 29, 2015 14:03
Show Gist options
  • Save poppe1219/6ca09cbf2ff98d449ccf to your computer and use it in GitHub Desktop.
Save poppe1219/6ca09cbf2ff98d449ccf to your computer and use it in GitHub Desktop.
An example module for parsing json with JS style comments.
"""An example module for parsing json with JS style comments.
Primarily intended for parsing config files in json format,
where the use of comments may be desirable.
As Douglas Crockford suggests:
"Suppose you are using JSON to keep configuration files,
which you would like to annotate. Go ahead and insert all
the comments you like. Then pipe it through JSMin before
handing it to your JSON parser."
(https://plus.google.com/+DouglasCrockfordEsq/posts/RK8qyGVaGSr)
Inspired by Damien Riquet's example:
http://www.lifl.fr/~riquetd/parse-a-json-file-with-comments.html
"""
import re
import json
def loads(text, parse_comments=True):
"""Parse a json text, with the option to parse out comments (JS style)."""
if parse_comments:
regex = re.compile(r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
re.DOTALL | re.MULTILINE
)
match = regex.search(text)
while match:
text = text[:match.start()] + text[match.end():]
match = regex.search(text)
return json.loads(text)
# pylint: disable=missing-docstring
# pylint: disable=too-many-public-methods
# pylint: disable=line-too-long
import unittest
import json_with_comments as jsontools
class TestConfigManage(unittest.TestCase):
def test_a_loads(self):
text1 = '{\n "key": "value"\n}'
text2 = '{\r\n "key": "value"\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_b_loads(self):
text1 = '{\n "key": "value" // JavaScript single line comment.\n}'
text2 = '{\r\n "key": "value" // JavaScript single line comment.\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_c_loads(self):
text1 = '{\n // JavaScript single line comment.\n "key": "value"\n}'
text2 = '{\r\n // JavaScript single line comment.\r\n "key": "value"\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_d_loads(self):
text1 = '{\n "key": "value"\n // JavaScript single line comment.\n}'
text2 = '{\r\n "key": "value"\r\n // JavaScript single line comment.\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_e_loads(self):
text1 = '// JavaScript single line comment.\n{\n "key": "value"\n}'
text2 = '// JavaScript single line comment.\r\n{\r\n "key": "value"\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_f_loads(self):
text1 = '{\n "key": "value" /* JavaScript multiline comment. */\n}'
text2 = '{\r\n "key": "value" /* JavaScript multiline comment. */\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_g_loads(self):
text1 = '{\n "key": "value" /*\n JavaScript\n multiline\n comment. */\n}'
text2 = '{\r\n "key": "value" /*\r\n JavaScript\r\n multiline\r\n comment. */\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_h_loads(self):
text1 = '{\n /*\n JavaScript\n multiline\n comment.\n */\n "key": "value"\n}'
text2 = '{\r\n /*\r\n JavaScript\r\n multiline\r\n comment.\r\n */\r\n "key": "value"\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_i_loads(self):
text1 = '/*\n JavaScript\n multiline\n comment.\n */\n {\n "key": "value"\n}'
text2 = '/*\r\n JavaScript\r\n multiline\r\n comment.\r\n */\r\n {\r\n "key": "value"\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_j_loads(self):
text1 = '/*\n JavaScript\n multiline\n comment.\n */\n {\n "key": "value" // JavaScript single line comment.\n}'
text2 = '/*\r\n JavaScript\r\n multiline\r\n comment.\r\n */\r\n {\r\n "key": "value" // JavaScript single line comment.\r\n}'
parsed1 = jsontools.loads(text1)
parsed2 = jsontools.loads(text2)
self.assertEqual(parsed1, {"key": "value"})
self.assertEqual(parsed2, {"key": "value"})
def test_loads_exception(self):
text1 = '/*\n JavaScript\n multiline\n comment.\n */\n {\n "key": "value" // JavaScript single line comment.\n}'
self.assertRaises(ValueError, jsontools.loads, text1, False)
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment