Last active
August 29, 2015 14:03
-
-
Save poppe1219/6ca09cbf2ff98d449ccf to your computer and use it in GitHub Desktop.
An example module for parsing json with JS style comments.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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