Basic implementation of a JSON parser written in pure Python and created as a drop-in replacement (well, almost) for the json
module in environments using very old Python versions (2.2
and lower).
Provides loads
, dumps
and their counterparts load
and dump
.
Please note that speed is clearly not the focus here...
-
Same function names and signature:
loads
,dumps
,load
,dump
; -
Handles all base JSON types:
- Arrays:
[]
- Objects:
{}
- Strings:
""
- Numbers: integers (
3
), floating point (3.14
), exponential (3.14e10
) - Boolean:
true
andfalse
- Null:
null
- Arrays:
-
Handles nested data structures, such as:
{ "key": "value", "nested": [{"name": "first", "elems": [1, true, null]}] }
If passed through the
loads(...)
method will return:{'key': 'value', 'nested': [{'name': 'first', 'elems': [1, True, None]}]}
Infinity
andNaN
currently do not follow strictly thejson
module rules (still noallow_nan
parameter).- If using this module on Python 2.3 and lower you MUST pass
truthy_value
andfalsy_value
;
These are some known bugs that will be fixed in the next releases:
-
Does not convert unicode strings to the respective character and viceversa (e.g.
\u1eb7
is not converted toặ
).>>> json.loads('"\\u1eb7 \\u00a3"') - ORIGINAL: 'ặ £' - THIS : '\\u1eb7 \\u00a3' >>> json.dumps('ặ £') - ORIGINAL: '"\\u1eb7 \\u00a3"' - THIS : '"ặ £"'
-
Has some problems with backslashes (e.g.
\n
is not converted to\\n
).>>> json.loads(r'"\" \\ \/ \b \f \n \r \t"') - ORIGINAL: '" \\ / \x08 \x0c \n \r \t' - THIS : '" \\ / \x08 \x0c \n \r \t' >>> json.dumps('" \\ / \x08 \x0c \n \r \t') - ORIGINAL: '"\\" \\\\ / \\b \\f \\n \\r \\t"' - THIS : '"\\" \\\\ / \x08 \x0c \n \r \t"'
These are some valid alternatives if this is not what you're looking for (as it probably is and should be), ordered by minimum supported version.
Library | Description | Built-in | Supported Python versions |
---|---|---|---|
simplejson/python2.2
|
Branch of the simplejson library that mantains backwards compatibility with Python 2.2.
Makes use of generator functions that were introduced in Python 2.2 (via PEP 255).
|
No |
Python >= 2.2
|
demjson
|
Feature rich module that uses only built-in methods and allows to encode, decode and syntax-checking JSON data. | No |
Python >= 2.4
|
simplejson
|
Externally maintained development version of the built-in json library included with Python.
|
No |
Python >= 2.5
|
json
|
Built-in library included with Python. | Yes |
Python >= 2.6
|
orjson
|
Fast JSON library written in Rust that serializes various data structures, such as dataclass , datetime /date /time and numpy.ndarray instances.
|
No |
CPython >= 3.7
|
ujson
|
Ultra fast JSON encoder and decoder written in pure C. | No |
Python >= 3.7
|
python-rapidjson
|
Python 3 wrapper around RapidJSON , an extremely fast C++ JSON parser and serialization library
|
No |
Python >= 3.x (unknown minor) |
- Clone the repository
- Install with
poetry install --with dev
Tests ensure that changes to the codebase do not break existing features and that anything works as expected.
To launch the tests run the following command:
poetry run poe test
Please make sure to...
- ... keep existing tests up-to-date with the latest changes;
- ... write relative tests when adding new features.
When writing tests please keep the in mind that:
- test files MUST be written for
unittest
; - test cases names MUST be a descriptive name written in PascalCase and end with
TestCase
(e.g.class MyTestCase(unittest.TestCase):
); - test names MUST be a descriptive name written in snake_case (all lowercase, with words separated with an underscore) and start with
test_
(e.g.def test_feature(self):
); - MAY use the
setUp()
andteardown()
methods to define instructions that will be executed before and after each test method; - each test MUST contain at least one
self.assert*
method call (we don't want empty no-op tests);
The following is an example of agood test from the official Python documentation:
import unittest
class WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget('The widget')
def tearDown(self):
self.widget.dispose()
def test_default_widget_size(self):
self.assertEqual(
self.widget.size(),
(50,50),
'incorrect default size'
)
def test_widget_resize(self):
self.widget.resize(100,150)
self.assertEqual(
self.widget.size(),
(100,150),
'wrong size after resize'
)