jsonxox 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jsonxox-0.8.0/LICENSE.md +21 -0
- jsonxox-0.8.0/PKG-INFO +179 -0
- jsonxox-0.8.0/README.md +146 -0
- jsonxox-0.8.0/pyproject.toml +77 -0
- jsonxox-0.8.0/requirements.development.txt +5 -0
- jsonxox-0.8.0/requirements.distribution.txt +4 -0
- jsonxox-0.8.0/requirements.txt +1 -0
- jsonxox-0.8.0/setup.cfg +4 -0
- jsonxox-0.8.0/source/jsonxox/__init__.py +103 -0
- jsonxox-0.8.0/source/jsonxox/version.txt +1 -0
- jsonxox-0.8.0/source/jsonxox.egg-info/PKG-INFO +179 -0
- jsonxox-0.8.0/source/jsonxox.egg-info/SOURCES.txt +15 -0
- jsonxox-0.8.0/source/jsonxox.egg-info/dependency_links.txt +1 -0
- jsonxox-0.8.0/source/jsonxox.egg-info/requires.txt +11 -0
- jsonxox-0.8.0/source/jsonxox.egg-info/top_level.txt +1 -0
- jsonxox-0.8.0/source/jsonxox.egg-info/zip-safe +1 -0
- jsonxox-0.8.0/tests/test_jsonxox.py +281 -0
jsonxox-0.8.0/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright © 2023–2026 Daniel Sissman.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
jsonxox-0.8.0/PKG-INFO
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jsonxox
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: Parsing for extended JSON with optional comments and trailing commas
|
|
5
|
+
Author: Daniel Sissman
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: documentation, https://github.com/bluebinary/jsonxox/blob/main/README.md
|
|
8
|
+
Project-URL: changelog, https://github.com/bluebinary/jsonxox/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: repository, https://github.com/bluebinary/jsonxox
|
|
10
|
+
Project-URL: issues, https://github.com/bluebinary/jsonxox/issues
|
|
11
|
+
Project-URL: homepage, https://github.com/bluebinary/jsonxox
|
|
12
|
+
Keywords: json,extened json,json with comments,json with trailing commas
|
|
13
|
+
Platform: any
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE.md
|
|
23
|
+
Provides-Extra: development
|
|
24
|
+
Requires-Dist: black==26.1.*; extra == "development"
|
|
25
|
+
Requires-Dist: pytest==9.0.*; extra == "development"
|
|
26
|
+
Requires-Dist: pytest-codeblocks==0.17.*; extra == "development"
|
|
27
|
+
Requires-Dist: pyflakes==3.4.*; extra == "development"
|
|
28
|
+
Provides-Extra: distribution
|
|
29
|
+
Requires-Dist: build; extra == "distribution"
|
|
30
|
+
Requires-Dist: twine; extra == "distribution"
|
|
31
|
+
Requires-Dist: wheel; extra == "distribution"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# JSONXOX: Extended JSON Parsing
|
|
35
|
+
|
|
36
|
+
Do you love the JSON serialization format but wish it included support for optional
|
|
37
|
+
comments and trailing commas? Well if so, the JSONXOX library is for you.
|
|
38
|
+
|
|
39
|
+
The JSONXOX library provides support for parsing extended JSON files and strings – JSON
|
|
40
|
+
files and strings which may contain optional C-style single-line and multi-line comments
|
|
41
|
+
as well as trailing commas.
|
|
42
|
+
|
|
43
|
+
### Requirements
|
|
44
|
+
|
|
45
|
+
The JSONXOX library has been tested with Python 3.10, 3.11, 3.12, 3.13 and 3.14. The
|
|
46
|
+
library has not been tested with, nor is it likely compatible with Python 3.9 and earlier.
|
|
47
|
+
|
|
48
|
+
### Installation
|
|
49
|
+
|
|
50
|
+
The JSONXOX library is available from PyPI, so may be added to a project's dependencies
|
|
51
|
+
via its `requirements.txt` file or similar by referencing the JSONXOX library's name,
|
|
52
|
+
`jsonxox`, or the library may be installed directly into the local runtime environment
|
|
53
|
+
using `pip install` by running the following command:
|
|
54
|
+
|
|
55
|
+
$ pip install jsonxox
|
|
56
|
+
|
|
57
|
+
### Usage Example
|
|
58
|
+
|
|
59
|
+
To use the JSONXOX library, simply import the library into your project as a drop-in
|
|
60
|
+
replacement for the standard `json` library, and use it as you would to load a JSON file
|
|
61
|
+
or JSON string. The library can be used to load standard JSON files and strings as well
|
|
62
|
+
as extended JSON files and strings containing single- and multi-line comments as well as
|
|
63
|
+
trailing commas. The library can also be used to save standard JSON files and strings.
|
|
64
|
+
|
|
65
|
+
See the [**Methods**](#methods) section for more information about the methods provided
|
|
66
|
+
by the library.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import jsonxox
|
|
70
|
+
|
|
71
|
+
sample: str = """
|
|
72
|
+
/* this is a multi-line comment block
|
|
73
|
+
that can span multiple lines or just a single line
|
|
74
|
+
*/
|
|
75
|
+
{
|
|
76
|
+
"a": 123, /* this is also a multi-line comment block (using a single line) */
|
|
77
|
+
// this is a single-line comment
|
|
78
|
+
"b": "456", // notice the trailing comma
|
|
79
|
+
}
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
data = jsonxox.loads(sample)
|
|
83
|
+
|
|
84
|
+
assert isinstance(data, dict)
|
|
85
|
+
|
|
86
|
+
assert "a" in data
|
|
87
|
+
assert data["a"] == 123
|
|
88
|
+
|
|
89
|
+
assert "b" in data
|
|
90
|
+
assert data["b"] == "456"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
<a id="methods"></a>
|
|
94
|
+
### Methods
|
|
95
|
+
|
|
96
|
+
The `jsonxox` library provides the following methods, mirroring the standard `json`
|
|
97
|
+
library in its available methods and overall functionality:
|
|
98
|
+
|
|
99
|
+
* `load(handle, **kwargs)` (`object`) – The `load()` method takes a file handle or file
|
|
100
|
+
handle like object that is an instance of `io.TextIOWrapper` or one of its subclasses
|
|
101
|
+
as input and removes any single and multi-line comments as well as any trailing commas
|
|
102
|
+
from the input string contents read from the file handle, and then passes the cleaned
|
|
103
|
+
string to the standard library's `json.loads()` method for quick deserialization to its
|
|
104
|
+
corresponding Python data types. Any additional keyword arguments are passed to the
|
|
105
|
+
`json.loads()` method, as such any additional keyword arguments must be compatible with
|
|
106
|
+
the `json.loads()` method.
|
|
107
|
+
|
|
108
|
+
* `loads(handle, **kwargs)` (`object`) – The `loads()` method takes a string as input
|
|
109
|
+
and removes any single and multi-line comments as well as any trailing commas from the
|
|
110
|
+
input string, and then passes the cleaned string to the standard library's `json.loads()`
|
|
111
|
+
method for quick deserialization to its corresponding Python data types. Any additional
|
|
112
|
+
keyword arguments are passed to the `json.loads()` method, as such any additional
|
|
113
|
+
keyword arguments must be compatible with the `json.loads()` method
|
|
114
|
+
|
|
115
|
+
* `dump(*args, **kwargs)` – The `dump()` method is a passthrough to the standard
|
|
116
|
+
`json` library's `dump()` method and accepts the same arguments and has the same return
|
|
117
|
+
values. Note that the `dump()` method cannot be used to re-save any comments or trailing
|
|
118
|
+
commas that may have been present in the original extended JSON file or string.
|
|
119
|
+
|
|
120
|
+
* `dumps(*args, **kwargs)` (`str`) – The `dumps()` method is a passthrough to the standard
|
|
121
|
+
`json` library's `dumps()` method and accepts the same arguments and has the same return
|
|
122
|
+
values. Note that the `dumps()` method cannot be used to re-save any comments or trailing
|
|
123
|
+
commas that may have been present in the original extended JSON file or string.
|
|
124
|
+
|
|
125
|
+
### Classes
|
|
126
|
+
|
|
127
|
+
The `jsonxox` library provides the following classes, mirroring the standard `json`
|
|
128
|
+
library in its available classes:
|
|
129
|
+
|
|
130
|
+
* `JSONDecoder` – The `JSONDecoder` class is a direct import of and reference to the
|
|
131
|
+
standard `json` library's `JSONDecoder` class.
|
|
132
|
+
|
|
133
|
+
* `JSONEncoder` – The `JSONEncoder` class is a direct import of and reference to the
|
|
134
|
+
standard `json` library's `JSONEncoder` class.
|
|
135
|
+
|
|
136
|
+
### Exceptions
|
|
137
|
+
|
|
138
|
+
The `jsonxox` library provides the following exception classes, mirroring the standard
|
|
139
|
+
`json` library in its available exception classes:
|
|
140
|
+
|
|
141
|
+
* `JSONDecodeError` – The `JSONDecodeError` exception class is a direct import of and
|
|
142
|
+
reference to the standard `json` library's `JSONDecodeError` exception class.
|
|
143
|
+
|
|
144
|
+
* `JSONXOXDecodeError` – The `JSONXOXDecodeError` exception class is a subclass of the
|
|
145
|
+
standard `json` library's `JSONDecodeError` class and will be raised by the `jsonxox`
|
|
146
|
+
library if an exception occurs while attempting to clean or load the JSON input.
|
|
147
|
+
|
|
148
|
+
### Unit Tests
|
|
149
|
+
|
|
150
|
+
The JSONXOX library includes a suite of comprehensive unit tests which ensure that the
|
|
151
|
+
library functionality operates as expected. The unit tests were developed with and are
|
|
152
|
+
run via `pytest`.
|
|
153
|
+
|
|
154
|
+
To ensure that the unit tests are run within a predictable runtime environment where all
|
|
155
|
+
of the necessary dependencies are available, a [Docker](https://www.docker.com) image is
|
|
156
|
+
created within which the tests are run. To run the unit tests, ensure Docker and Docker
|
|
157
|
+
Compose is [installed](https://docs.docker.com/engine/install/), and perform the
|
|
158
|
+
following commands, which will build the Docker image via `docker compose build` and
|
|
159
|
+
then run the tests via `docker compose run` – the output the tests will be displayed:
|
|
160
|
+
|
|
161
|
+
```shell
|
|
162
|
+
$ docker compose build
|
|
163
|
+
$ docker compose run tests
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
To run the unit tests with optional command line arguments being passed to `pytest`,
|
|
167
|
+
append the relevant arguments to the `docker compose run tests` command, as follows, for
|
|
168
|
+
example passing `-v` to enable verbose output and `-s` to print standard output:
|
|
169
|
+
|
|
170
|
+
```shell
|
|
171
|
+
$ docker compose run tests -v -s
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
See the documentation for [PyTest](https://docs.pytest.org/en/latest/) regarding
|
|
175
|
+
available optional command line arguments.
|
|
176
|
+
|
|
177
|
+
### Copyright & License Information
|
|
178
|
+
|
|
179
|
+
Copyright © 2023–2026 Daniel Sissman; licensed under the MIT License.
|
jsonxox-0.8.0/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# JSONXOX: Extended JSON Parsing
|
|
2
|
+
|
|
3
|
+
Do you love the JSON serialization format but wish it included support for optional
|
|
4
|
+
comments and trailing commas? Well if so, the JSONXOX library is for you.
|
|
5
|
+
|
|
6
|
+
The JSONXOX library provides support for parsing extended JSON files and strings – JSON
|
|
7
|
+
files and strings which may contain optional C-style single-line and multi-line comments
|
|
8
|
+
as well as trailing commas.
|
|
9
|
+
|
|
10
|
+
### Requirements
|
|
11
|
+
|
|
12
|
+
The JSONXOX library has been tested with Python 3.10, 3.11, 3.12, 3.13 and 3.14. The
|
|
13
|
+
library has not been tested with, nor is it likely compatible with Python 3.9 and earlier.
|
|
14
|
+
|
|
15
|
+
### Installation
|
|
16
|
+
|
|
17
|
+
The JSONXOX library is available from PyPI, so may be added to a project's dependencies
|
|
18
|
+
via its `requirements.txt` file or similar by referencing the JSONXOX library's name,
|
|
19
|
+
`jsonxox`, or the library may be installed directly into the local runtime environment
|
|
20
|
+
using `pip install` by running the following command:
|
|
21
|
+
|
|
22
|
+
$ pip install jsonxox
|
|
23
|
+
|
|
24
|
+
### Usage Example
|
|
25
|
+
|
|
26
|
+
To use the JSONXOX library, simply import the library into your project as a drop-in
|
|
27
|
+
replacement for the standard `json` library, and use it as you would to load a JSON file
|
|
28
|
+
or JSON string. The library can be used to load standard JSON files and strings as well
|
|
29
|
+
as extended JSON files and strings containing single- and multi-line comments as well as
|
|
30
|
+
trailing commas. The library can also be used to save standard JSON files and strings.
|
|
31
|
+
|
|
32
|
+
See the [**Methods**](#methods) section for more information about the methods provided
|
|
33
|
+
by the library.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import jsonxox
|
|
37
|
+
|
|
38
|
+
sample: str = """
|
|
39
|
+
/* this is a multi-line comment block
|
|
40
|
+
that can span multiple lines or just a single line
|
|
41
|
+
*/
|
|
42
|
+
{
|
|
43
|
+
"a": 123, /* this is also a multi-line comment block (using a single line) */
|
|
44
|
+
// this is a single-line comment
|
|
45
|
+
"b": "456", // notice the trailing comma
|
|
46
|
+
}
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
data = jsonxox.loads(sample)
|
|
50
|
+
|
|
51
|
+
assert isinstance(data, dict)
|
|
52
|
+
|
|
53
|
+
assert "a" in data
|
|
54
|
+
assert data["a"] == 123
|
|
55
|
+
|
|
56
|
+
assert "b" in data
|
|
57
|
+
assert data["b"] == "456"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
<a id="methods"></a>
|
|
61
|
+
### Methods
|
|
62
|
+
|
|
63
|
+
The `jsonxox` library provides the following methods, mirroring the standard `json`
|
|
64
|
+
library in its available methods and overall functionality:
|
|
65
|
+
|
|
66
|
+
* `load(handle, **kwargs)` (`object`) – The `load()` method takes a file handle or file
|
|
67
|
+
handle like object that is an instance of `io.TextIOWrapper` or one of its subclasses
|
|
68
|
+
as input and removes any single and multi-line comments as well as any trailing commas
|
|
69
|
+
from the input string contents read from the file handle, and then passes the cleaned
|
|
70
|
+
string to the standard library's `json.loads()` method for quick deserialization to its
|
|
71
|
+
corresponding Python data types. Any additional keyword arguments are passed to the
|
|
72
|
+
`json.loads()` method, as such any additional keyword arguments must be compatible with
|
|
73
|
+
the `json.loads()` method.
|
|
74
|
+
|
|
75
|
+
* `loads(handle, **kwargs)` (`object`) – The `loads()` method takes a string as input
|
|
76
|
+
and removes any single and multi-line comments as well as any trailing commas from the
|
|
77
|
+
input string, and then passes the cleaned string to the standard library's `json.loads()`
|
|
78
|
+
method for quick deserialization to its corresponding Python data types. Any additional
|
|
79
|
+
keyword arguments are passed to the `json.loads()` method, as such any additional
|
|
80
|
+
keyword arguments must be compatible with the `json.loads()` method
|
|
81
|
+
|
|
82
|
+
* `dump(*args, **kwargs)` – The `dump()` method is a passthrough to the standard
|
|
83
|
+
`json` library's `dump()` method and accepts the same arguments and has the same return
|
|
84
|
+
values. Note that the `dump()` method cannot be used to re-save any comments or trailing
|
|
85
|
+
commas that may have been present in the original extended JSON file or string.
|
|
86
|
+
|
|
87
|
+
* `dumps(*args, **kwargs)` (`str`) – The `dumps()` method is a passthrough to the standard
|
|
88
|
+
`json` library's `dumps()` method and accepts the same arguments and has the same return
|
|
89
|
+
values. Note that the `dumps()` method cannot be used to re-save any comments or trailing
|
|
90
|
+
commas that may have been present in the original extended JSON file or string.
|
|
91
|
+
|
|
92
|
+
### Classes
|
|
93
|
+
|
|
94
|
+
The `jsonxox` library provides the following classes, mirroring the standard `json`
|
|
95
|
+
library in its available classes:
|
|
96
|
+
|
|
97
|
+
* `JSONDecoder` – The `JSONDecoder` class is a direct import of and reference to the
|
|
98
|
+
standard `json` library's `JSONDecoder` class.
|
|
99
|
+
|
|
100
|
+
* `JSONEncoder` – The `JSONEncoder` class is a direct import of and reference to the
|
|
101
|
+
standard `json` library's `JSONEncoder` class.
|
|
102
|
+
|
|
103
|
+
### Exceptions
|
|
104
|
+
|
|
105
|
+
The `jsonxox` library provides the following exception classes, mirroring the standard
|
|
106
|
+
`json` library in its available exception classes:
|
|
107
|
+
|
|
108
|
+
* `JSONDecodeError` – The `JSONDecodeError` exception class is a direct import of and
|
|
109
|
+
reference to the standard `json` library's `JSONDecodeError` exception class.
|
|
110
|
+
|
|
111
|
+
* `JSONXOXDecodeError` – The `JSONXOXDecodeError` exception class is a subclass of the
|
|
112
|
+
standard `json` library's `JSONDecodeError` class and will be raised by the `jsonxox`
|
|
113
|
+
library if an exception occurs while attempting to clean or load the JSON input.
|
|
114
|
+
|
|
115
|
+
### Unit Tests
|
|
116
|
+
|
|
117
|
+
The JSONXOX library includes a suite of comprehensive unit tests which ensure that the
|
|
118
|
+
library functionality operates as expected. The unit tests were developed with and are
|
|
119
|
+
run via `pytest`.
|
|
120
|
+
|
|
121
|
+
To ensure that the unit tests are run within a predictable runtime environment where all
|
|
122
|
+
of the necessary dependencies are available, a [Docker](https://www.docker.com) image is
|
|
123
|
+
created within which the tests are run. To run the unit tests, ensure Docker and Docker
|
|
124
|
+
Compose is [installed](https://docs.docker.com/engine/install/), and perform the
|
|
125
|
+
following commands, which will build the Docker image via `docker compose build` and
|
|
126
|
+
then run the tests via `docker compose run` – the output the tests will be displayed:
|
|
127
|
+
|
|
128
|
+
```shell
|
|
129
|
+
$ docker compose build
|
|
130
|
+
$ docker compose run tests
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
To run the unit tests with optional command line arguments being passed to `pytest`,
|
|
134
|
+
append the relevant arguments to the `docker compose run tests` command, as follows, for
|
|
135
|
+
example passing `-v` to enable verbose output and `-s` to print standard output:
|
|
136
|
+
|
|
137
|
+
```shell
|
|
138
|
+
$ docker compose run tests -v -s
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
See the documentation for [PyTest](https://docs.pytest.org/en/latest/) regarding
|
|
142
|
+
available optional command line arguments.
|
|
143
|
+
|
|
144
|
+
### Copyright & License Information
|
|
145
|
+
|
|
146
|
+
Copyright © 2023–2026 Daniel Sissman; licensed under the MIT License.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "jsonxox"
|
|
3
|
+
description = "Parsing for extended JSON with optional comments and trailing commas"
|
|
4
|
+
readme = {file = "README.md", content-type = "text/markdown"}
|
|
5
|
+
keywords = ["json", "extened json", "json with comments", "json with trailing commas"]
|
|
6
|
+
authors = [{name = "Daniel Sissman"}]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
classifiers = [
|
|
9
|
+
"Programming Language :: Python :: 3",
|
|
10
|
+
"Programming Language :: Python :: 3.10",
|
|
11
|
+
"Programming Language :: Python :: 3.11",
|
|
12
|
+
"Programming Language :: Python :: 3.12",
|
|
13
|
+
"Programming Language :: Python :: 3.13",
|
|
14
|
+
"Programming Language :: Python :: 3.14",
|
|
15
|
+
]
|
|
16
|
+
requires-python = ">=3.10"
|
|
17
|
+
dynamic = [
|
|
18
|
+
"version",
|
|
19
|
+
"dependencies",
|
|
20
|
+
"optional-dependencies",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
documentation = "https://github.com/bluebinary/jsonxox/blob/main/README.md"
|
|
25
|
+
changelog = "https://github.com/bluebinary/jsonxox/blob/main/CHANGELOG.md"
|
|
26
|
+
repository = "https://github.com/bluebinary/jsonxox"
|
|
27
|
+
issues = "https://github.com/bluebinary/jsonxox/issues"
|
|
28
|
+
homepage = "https://github.com/bluebinary/jsonxox"
|
|
29
|
+
|
|
30
|
+
[build-system]
|
|
31
|
+
requires = ["setuptools", "wheel"]
|
|
32
|
+
build-backend = "setuptools.build_meta"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.dynamic]
|
|
35
|
+
version = {file = "source/jsonxox/version.txt"}
|
|
36
|
+
dependencies = {file = "requirements.txt"}
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.dynamic.optional-dependencies]
|
|
39
|
+
development = {file = "requirements.development.txt"}
|
|
40
|
+
distribution = {file = "requirements.distribution.txt"}
|
|
41
|
+
|
|
42
|
+
[tool.setuptools]
|
|
43
|
+
platforms = ["any"]
|
|
44
|
+
zip-safe = true
|
|
45
|
+
include-package-data = true
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["source"]
|
|
49
|
+
exclude = ["resources*", "tests*", "*#*"]
|
|
50
|
+
|
|
51
|
+
[tool.setuptools.package-data]
|
|
52
|
+
"*" = ["*.json", "*.jsonx", "*.jsonc"]
|
|
53
|
+
source = ["*.json", "*.jsonx", "*.jsonc"]
|
|
54
|
+
tests = ["tests/data/*.json", "tests/data/*.jsonx", "tests/data/*.jsonc"]
|
|
55
|
+
|
|
56
|
+
[tool.setuptools.exclude-package-data]
|
|
57
|
+
"*" = ["*#*", "#*", "@*"]
|
|
58
|
+
|
|
59
|
+
[tool.pytest.ini_options]
|
|
60
|
+
minversion = "6.0"
|
|
61
|
+
addopts = "-ra -q"
|
|
62
|
+
testpaths = [
|
|
63
|
+
"tests"
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[tool.black]
|
|
67
|
+
line-length = 88
|
|
68
|
+
target-version = ["py310"]
|
|
69
|
+
include = '\.pyi?$'
|
|
70
|
+
extend-exclude = '''
|
|
71
|
+
/(
|
|
72
|
+
# The following are specific to Black, you probably don't want those.
|
|
73
|
+
| blib2to3
|
|
74
|
+
| tests/data
|
|
75
|
+
| profiling
|
|
76
|
+
)/
|
|
77
|
+
'''
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# JSONXOX Library: Runtime Dependencies
|
jsonxox-0.8.0/setup.cfg
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import re
|
|
3
|
+
import io
|
|
4
|
+
|
|
5
|
+
from json import (
|
|
6
|
+
JSONDecoder,
|
|
7
|
+
JSONEncoder,
|
|
8
|
+
JSONDecodeError,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class JSONXOXDecodeError(JSONDecodeError):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _jsonx_to_json(content: str) -> str:
|
|
17
|
+
"""With an extended JSON string as input (JSON that can contain C-style single and
|
|
18
|
+
multi-line comments as well as trailing commas) and return a standard JSON string
|
|
19
|
+
that has had these non-standard elements removed."""
|
|
20
|
+
|
|
21
|
+
if not isinstance(content, str):
|
|
22
|
+
raise TypeError("The 'content' argument must have a string value!")
|
|
23
|
+
|
|
24
|
+
if len(content) > 0:
|
|
25
|
+
flags = re.MULTILINE | re.DOTALL
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
# Remove multi-line comments that begin with /* and end with */
|
|
29
|
+
content = re.sub(r"\/\*.*?\*\/", "", content, flags=flags)
|
|
30
|
+
|
|
31
|
+
# Remove single-line comments which begin with // and end at a newline, } or ]
|
|
32
|
+
content = re.sub(r"\s*(#|\/\/)([^\n\}\]]*)", "", content, flags=flags)
|
|
33
|
+
|
|
34
|
+
# Remove any trailing commas that are present before block closures
|
|
35
|
+
content = re.sub(r"\,(\s*)(\]|\})", r"\1\2", content, flags=flags)
|
|
36
|
+
except Exception as exception:
|
|
37
|
+
raise JSONXOXDecodeError(
|
|
38
|
+
"An exception occurred while cleaning the JSON: %s" % (str(exception))
|
|
39
|
+
) from exception
|
|
40
|
+
|
|
41
|
+
return content.strip()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def load(handle, **kwargs) -> object | None:
|
|
45
|
+
"""An extended json.load() method which supports loading JSON files with single and
|
|
46
|
+
multi-line comments as well as trailing commas."""
|
|
47
|
+
|
|
48
|
+
if not isinstance(handle, io.TextIOWrapper):
|
|
49
|
+
raise RuntimeError("The input must be compatible with io.TextIOWrapper!")
|
|
50
|
+
|
|
51
|
+
content = handle.read().strip()
|
|
52
|
+
|
|
53
|
+
if len(content) > 0:
|
|
54
|
+
if content := _jsonx_to_json(content):
|
|
55
|
+
try:
|
|
56
|
+
if isinstance(data := json.loads(content, **kwargs), object):
|
|
57
|
+
return data
|
|
58
|
+
except JSONDecodeError as exception:
|
|
59
|
+
raise JSONXOXDecodeError(str(exception)) from exception
|
|
60
|
+
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def loads(content: str, **kwargs) -> object | None:
|
|
65
|
+
"""An extended json.loads() method which supports loading JSON files with single and
|
|
66
|
+
multi-line comments as well as trailing commas."""
|
|
67
|
+
|
|
68
|
+
if not isinstance(content, str):
|
|
69
|
+
raise TypeError("The 'content' argument must have a string value!")
|
|
70
|
+
|
|
71
|
+
if len(content) > 0:
|
|
72
|
+
if content := _jsonx_to_json(content):
|
|
73
|
+
try:
|
|
74
|
+
if isinstance(data := json.loads(content, **kwargs), object):
|
|
75
|
+
return data
|
|
76
|
+
except JSONDecodeError as exception:
|
|
77
|
+
raise JSONXOXDecodeError(str(exception)) from exception
|
|
78
|
+
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def dump(*args, **kwargs):
|
|
83
|
+
"""A passthrough method for the json standard library's .dump() method."""
|
|
84
|
+
|
|
85
|
+
return json.dump(*args, **kwargs)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def dumps(*args, **kwargs):
|
|
89
|
+
"""A passthrough method for the json standard library's .dumps() method."""
|
|
90
|
+
|
|
91
|
+
return json.dumps(*args, **kwargs)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
__all__ = [
|
|
95
|
+
"load",
|
|
96
|
+
"loads",
|
|
97
|
+
"dump",
|
|
98
|
+
"dumps",
|
|
99
|
+
"JSONDecoder",
|
|
100
|
+
"JSONEncoder",
|
|
101
|
+
"JSONDecodeError",
|
|
102
|
+
"JSONXOXDecodeError",
|
|
103
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.8.0
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jsonxox
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: Parsing for extended JSON with optional comments and trailing commas
|
|
5
|
+
Author: Daniel Sissman
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: documentation, https://github.com/bluebinary/jsonxox/blob/main/README.md
|
|
8
|
+
Project-URL: changelog, https://github.com/bluebinary/jsonxox/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: repository, https://github.com/bluebinary/jsonxox
|
|
10
|
+
Project-URL: issues, https://github.com/bluebinary/jsonxox/issues
|
|
11
|
+
Project-URL: homepage, https://github.com/bluebinary/jsonxox
|
|
12
|
+
Keywords: json,extened json,json with comments,json with trailing commas
|
|
13
|
+
Platform: any
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE.md
|
|
23
|
+
Provides-Extra: development
|
|
24
|
+
Requires-Dist: black==26.1.*; extra == "development"
|
|
25
|
+
Requires-Dist: pytest==9.0.*; extra == "development"
|
|
26
|
+
Requires-Dist: pytest-codeblocks==0.17.*; extra == "development"
|
|
27
|
+
Requires-Dist: pyflakes==3.4.*; extra == "development"
|
|
28
|
+
Provides-Extra: distribution
|
|
29
|
+
Requires-Dist: build; extra == "distribution"
|
|
30
|
+
Requires-Dist: twine; extra == "distribution"
|
|
31
|
+
Requires-Dist: wheel; extra == "distribution"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# JSONXOX: Extended JSON Parsing
|
|
35
|
+
|
|
36
|
+
Do you love the JSON serialization format but wish it included support for optional
|
|
37
|
+
comments and trailing commas? Well if so, the JSONXOX library is for you.
|
|
38
|
+
|
|
39
|
+
The JSONXOX library provides support for parsing extended JSON files and strings – JSON
|
|
40
|
+
files and strings which may contain optional C-style single-line and multi-line comments
|
|
41
|
+
as well as trailing commas.
|
|
42
|
+
|
|
43
|
+
### Requirements
|
|
44
|
+
|
|
45
|
+
The JSONXOX library has been tested with Python 3.10, 3.11, 3.12, 3.13 and 3.14. The
|
|
46
|
+
library has not been tested with, nor is it likely compatible with Python 3.9 and earlier.
|
|
47
|
+
|
|
48
|
+
### Installation
|
|
49
|
+
|
|
50
|
+
The JSONXOX library is available from PyPI, so may be added to a project's dependencies
|
|
51
|
+
via its `requirements.txt` file or similar by referencing the JSONXOX library's name,
|
|
52
|
+
`jsonxox`, or the library may be installed directly into the local runtime environment
|
|
53
|
+
using `pip install` by running the following command:
|
|
54
|
+
|
|
55
|
+
$ pip install jsonxox
|
|
56
|
+
|
|
57
|
+
### Usage Example
|
|
58
|
+
|
|
59
|
+
To use the JSONXOX library, simply import the library into your project as a drop-in
|
|
60
|
+
replacement for the standard `json` library, and use it as you would to load a JSON file
|
|
61
|
+
or JSON string. The library can be used to load standard JSON files and strings as well
|
|
62
|
+
as extended JSON files and strings containing single- and multi-line comments as well as
|
|
63
|
+
trailing commas. The library can also be used to save standard JSON files and strings.
|
|
64
|
+
|
|
65
|
+
See the [**Methods**](#methods) section for more information about the methods provided
|
|
66
|
+
by the library.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import jsonxox
|
|
70
|
+
|
|
71
|
+
sample: str = """
|
|
72
|
+
/* this is a multi-line comment block
|
|
73
|
+
that can span multiple lines or just a single line
|
|
74
|
+
*/
|
|
75
|
+
{
|
|
76
|
+
"a": 123, /* this is also a multi-line comment block (using a single line) */
|
|
77
|
+
// this is a single-line comment
|
|
78
|
+
"b": "456", // notice the trailing comma
|
|
79
|
+
}
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
data = jsonxox.loads(sample)
|
|
83
|
+
|
|
84
|
+
assert isinstance(data, dict)
|
|
85
|
+
|
|
86
|
+
assert "a" in data
|
|
87
|
+
assert data["a"] == 123
|
|
88
|
+
|
|
89
|
+
assert "b" in data
|
|
90
|
+
assert data["b"] == "456"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
<a id="methods"></a>
|
|
94
|
+
### Methods
|
|
95
|
+
|
|
96
|
+
The `jsonxox` library provides the following methods, mirroring the standard `json`
|
|
97
|
+
library in its available methods and overall functionality:
|
|
98
|
+
|
|
99
|
+
* `load(handle, **kwargs)` (`object`) – The `load()` method takes a file handle or file
|
|
100
|
+
handle like object that is an instance of `io.TextIOWrapper` or one of its subclasses
|
|
101
|
+
as input and removes any single and multi-line comments as well as any trailing commas
|
|
102
|
+
from the input string contents read from the file handle, and then passes the cleaned
|
|
103
|
+
string to the standard library's `json.loads()` method for quick deserialization to its
|
|
104
|
+
corresponding Python data types. Any additional keyword arguments are passed to the
|
|
105
|
+
`json.loads()` method, as such any additional keyword arguments must be compatible with
|
|
106
|
+
the `json.loads()` method.
|
|
107
|
+
|
|
108
|
+
* `loads(handle, **kwargs)` (`object`) – The `loads()` method takes a string as input
|
|
109
|
+
and removes any single and multi-line comments as well as any trailing commas from the
|
|
110
|
+
input string, and then passes the cleaned string to the standard library's `json.loads()`
|
|
111
|
+
method for quick deserialization to its corresponding Python data types. Any additional
|
|
112
|
+
keyword arguments are passed to the `json.loads()` method, as such any additional
|
|
113
|
+
keyword arguments must be compatible with the `json.loads()` method
|
|
114
|
+
|
|
115
|
+
* `dump(*args, **kwargs)` – The `dump()` method is a passthrough to the standard
|
|
116
|
+
`json` library's `dump()` method and accepts the same arguments and has the same return
|
|
117
|
+
values. Note that the `dump()` method cannot be used to re-save any comments or trailing
|
|
118
|
+
commas that may have been present in the original extended JSON file or string.
|
|
119
|
+
|
|
120
|
+
* `dumps(*args, **kwargs)` (`str`) – The `dumps()` method is a passthrough to the standard
|
|
121
|
+
`json` library's `dumps()` method and accepts the same arguments and has the same return
|
|
122
|
+
values. Note that the `dumps()` method cannot be used to re-save any comments or trailing
|
|
123
|
+
commas that may have been present in the original extended JSON file or string.
|
|
124
|
+
|
|
125
|
+
### Classes
|
|
126
|
+
|
|
127
|
+
The `jsonxox` library provides the following classes, mirroring the standard `json`
|
|
128
|
+
library in its available classes:
|
|
129
|
+
|
|
130
|
+
* `JSONDecoder` – The `JSONDecoder` class is a direct import of and reference to the
|
|
131
|
+
standard `json` library's `JSONDecoder` class.
|
|
132
|
+
|
|
133
|
+
* `JSONEncoder` – The `JSONEncoder` class is a direct import of and reference to the
|
|
134
|
+
standard `json` library's `JSONEncoder` class.
|
|
135
|
+
|
|
136
|
+
### Exceptions
|
|
137
|
+
|
|
138
|
+
The `jsonxox` library provides the following exception classes, mirroring the standard
|
|
139
|
+
`json` library in its available exception classes:
|
|
140
|
+
|
|
141
|
+
* `JSONDecodeError` – The `JSONDecodeError` exception class is a direct import of and
|
|
142
|
+
reference to the standard `json` library's `JSONDecodeError` exception class.
|
|
143
|
+
|
|
144
|
+
* `JSONXOXDecodeError` – The `JSONXOXDecodeError` exception class is a subclass of the
|
|
145
|
+
standard `json` library's `JSONDecodeError` class and will be raised by the `jsonxox`
|
|
146
|
+
library if an exception occurs while attempting to clean or load the JSON input.
|
|
147
|
+
|
|
148
|
+
### Unit Tests
|
|
149
|
+
|
|
150
|
+
The JSONXOX library includes a suite of comprehensive unit tests which ensure that the
|
|
151
|
+
library functionality operates as expected. The unit tests were developed with and are
|
|
152
|
+
run via `pytest`.
|
|
153
|
+
|
|
154
|
+
To ensure that the unit tests are run within a predictable runtime environment where all
|
|
155
|
+
of the necessary dependencies are available, a [Docker](https://www.docker.com) image is
|
|
156
|
+
created within which the tests are run. To run the unit tests, ensure Docker and Docker
|
|
157
|
+
Compose is [installed](https://docs.docker.com/engine/install/), and perform the
|
|
158
|
+
following commands, which will build the Docker image via `docker compose build` and
|
|
159
|
+
then run the tests via `docker compose run` – the output the tests will be displayed:
|
|
160
|
+
|
|
161
|
+
```shell
|
|
162
|
+
$ docker compose build
|
|
163
|
+
$ docker compose run tests
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
To run the unit tests with optional command line arguments being passed to `pytest`,
|
|
167
|
+
append the relevant arguments to the `docker compose run tests` command, as follows, for
|
|
168
|
+
example passing `-v` to enable verbose output and `-s` to print standard output:
|
|
169
|
+
|
|
170
|
+
```shell
|
|
171
|
+
$ docker compose run tests -v -s
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
See the documentation for [PyTest](https://docs.pytest.org/en/latest/) regarding
|
|
175
|
+
available optional command line arguments.
|
|
176
|
+
|
|
177
|
+
### Copyright & License Information
|
|
178
|
+
|
|
179
|
+
Copyright © 2023–2026 Daniel Sissman; licensed under the MIT License.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
LICENSE.md
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
requirements.development.txt
|
|
5
|
+
requirements.distribution.txt
|
|
6
|
+
requirements.txt
|
|
7
|
+
source/jsonxox/__init__.py
|
|
8
|
+
source/jsonxox/version.txt
|
|
9
|
+
source/jsonxox.egg-info/PKG-INFO
|
|
10
|
+
source/jsonxox.egg-info/SOURCES.txt
|
|
11
|
+
source/jsonxox.egg-info/dependency_links.txt
|
|
12
|
+
source/jsonxox.egg-info/requires.txt
|
|
13
|
+
source/jsonxox.egg-info/top_level.txt
|
|
14
|
+
source/jsonxox.egg-info/zip-safe
|
|
15
|
+
tests/test_jsonxox.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
jsonxox
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import jsonxox
|
|
2
|
+
import io
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_jsonxox_loads_with_trailing_commas_indented(read: callable):
|
|
6
|
+
"""Text the jsonxox.loads() method."""
|
|
7
|
+
|
|
8
|
+
contents: str = read("examples/trailing-commas-indented.jsonx")
|
|
9
|
+
|
|
10
|
+
assert isinstance(contents, str)
|
|
11
|
+
|
|
12
|
+
data = jsonxox.loads(contents)
|
|
13
|
+
|
|
14
|
+
assert isinstance(data, dict)
|
|
15
|
+
|
|
16
|
+
assert "a" in data
|
|
17
|
+
assert data["a"] == 123
|
|
18
|
+
|
|
19
|
+
assert "b" in data
|
|
20
|
+
assert data["b"] == "456"
|
|
21
|
+
|
|
22
|
+
assert "c" in data
|
|
23
|
+
assert data["c"] == 789.10
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_jsonxox_loads_with_trailing_commas_compacted(read: callable):
|
|
27
|
+
"""Text the jsonxox.loads() method."""
|
|
28
|
+
|
|
29
|
+
contents: str = read("examples/trailing-commas-compacted.jsonx")
|
|
30
|
+
|
|
31
|
+
assert isinstance(contents, str)
|
|
32
|
+
|
|
33
|
+
data = jsonxox.loads(contents)
|
|
34
|
+
|
|
35
|
+
assert isinstance(data, dict)
|
|
36
|
+
|
|
37
|
+
assert "a" in data
|
|
38
|
+
assert data["a"] == 123
|
|
39
|
+
|
|
40
|
+
assert "b" in data
|
|
41
|
+
assert data["b"] == "456"
|
|
42
|
+
|
|
43
|
+
assert "c" in data
|
|
44
|
+
assert data["c"] == 789.10
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_jsonxox_loads_with_single_line_comments_indented(read: callable):
|
|
48
|
+
"""Text the jsonxox.loads() method."""
|
|
49
|
+
|
|
50
|
+
contents: str = read("examples/single-line-comments-indented.jsonx")
|
|
51
|
+
|
|
52
|
+
assert isinstance(contents, str)
|
|
53
|
+
|
|
54
|
+
data = jsonxox.loads(contents)
|
|
55
|
+
|
|
56
|
+
assert isinstance(data, dict)
|
|
57
|
+
|
|
58
|
+
assert "a" in data
|
|
59
|
+
assert data["a"] == 123
|
|
60
|
+
|
|
61
|
+
assert "b" in data
|
|
62
|
+
assert data["b"] == "456"
|
|
63
|
+
|
|
64
|
+
assert "c" in data
|
|
65
|
+
assert data["c"] == 789.10
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_jsonxox_loads_with_single_line_comments_compacted(read: callable):
|
|
69
|
+
"""Text the jsonxox.loads() method."""
|
|
70
|
+
|
|
71
|
+
contents: str = read("examples/single-line-comments-compacted.jsonx")
|
|
72
|
+
|
|
73
|
+
assert isinstance(contents, str)
|
|
74
|
+
|
|
75
|
+
data = jsonxox.loads(contents)
|
|
76
|
+
|
|
77
|
+
assert isinstance(data, dict)
|
|
78
|
+
|
|
79
|
+
assert "a" in data
|
|
80
|
+
assert data["a"] == 123
|
|
81
|
+
|
|
82
|
+
assert "b" in data
|
|
83
|
+
assert data["b"] == "456"
|
|
84
|
+
|
|
85
|
+
assert "c" in data
|
|
86
|
+
assert data["c"] == 789.10
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_jsonxox_loads_with_multi_line_comments_indented(read: callable):
|
|
90
|
+
"""Text the jsonxox.loads() method."""
|
|
91
|
+
|
|
92
|
+
contents: str = read("examples/multi-line-comments-indented.jsonx")
|
|
93
|
+
|
|
94
|
+
assert isinstance(contents, str)
|
|
95
|
+
|
|
96
|
+
data = jsonxox.loads(contents)
|
|
97
|
+
|
|
98
|
+
assert isinstance(data, dict)
|
|
99
|
+
|
|
100
|
+
assert "a" in data
|
|
101
|
+
assert data["a"] == 123
|
|
102
|
+
|
|
103
|
+
assert "b" in data
|
|
104
|
+
assert data["b"] == "456"
|
|
105
|
+
|
|
106
|
+
assert "c" in data
|
|
107
|
+
assert data["c"] == 789.10
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_jsonxox_loads_with_multi_line_comments_compacted(read: callable):
|
|
111
|
+
"""Text the jsonxox.loads() method."""
|
|
112
|
+
|
|
113
|
+
contents: str = read("examples/multi-line-comments-compacted.jsonx")
|
|
114
|
+
|
|
115
|
+
assert isinstance(contents, str)
|
|
116
|
+
|
|
117
|
+
data = jsonxox.loads(contents)
|
|
118
|
+
|
|
119
|
+
assert isinstance(data, dict)
|
|
120
|
+
|
|
121
|
+
assert "a" in data
|
|
122
|
+
assert data["a"] == 123
|
|
123
|
+
|
|
124
|
+
assert "b" in data
|
|
125
|
+
assert data["b"] == "456"
|
|
126
|
+
|
|
127
|
+
assert "c" in data
|
|
128
|
+
assert data["c"] == 789.10
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def test_jsonxox_load_with_all_combined_indented(path: callable):
|
|
132
|
+
"""Text the jsonxox.load() method."""
|
|
133
|
+
|
|
134
|
+
filepath: str = path("examples/all-combined-indented.jsonx")
|
|
135
|
+
|
|
136
|
+
assert isinstance(filepath, str)
|
|
137
|
+
|
|
138
|
+
with open(filepath, "r") as handle:
|
|
139
|
+
data = jsonxox.load(handle)
|
|
140
|
+
|
|
141
|
+
assert isinstance(data, dict)
|
|
142
|
+
|
|
143
|
+
assert "a" in data
|
|
144
|
+
assert data["a"] == 123
|
|
145
|
+
|
|
146
|
+
assert "b" in data
|
|
147
|
+
assert data["b"] == "456"
|
|
148
|
+
|
|
149
|
+
assert "c" in data
|
|
150
|
+
assert data["c"] == 789.10
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def test_jsonxox_load_with_all_combined_compacted(path: callable):
|
|
154
|
+
"""Text the jsonxox.load() method."""
|
|
155
|
+
|
|
156
|
+
filepath: str = path("examples/all-combined-compacted.jsonx")
|
|
157
|
+
|
|
158
|
+
assert isinstance(filepath, str)
|
|
159
|
+
|
|
160
|
+
with open(filepath, "r") as handle:
|
|
161
|
+
data = jsonxox.load(handle)
|
|
162
|
+
|
|
163
|
+
assert isinstance(data, dict)
|
|
164
|
+
|
|
165
|
+
assert "a" in data
|
|
166
|
+
assert data["a"] == 123
|
|
167
|
+
|
|
168
|
+
assert "b" in data
|
|
169
|
+
assert data["b"] == "456"
|
|
170
|
+
|
|
171
|
+
assert "c" in data
|
|
172
|
+
assert data["c"] == 789.10
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def test_jsonxox_loads_with_all_combined_indented(read: callable):
|
|
176
|
+
"""Text the jsonxox.loads() method."""
|
|
177
|
+
|
|
178
|
+
contents: str = read("examples/all-combined-indented.jsonx")
|
|
179
|
+
|
|
180
|
+
assert isinstance(contents, str)
|
|
181
|
+
|
|
182
|
+
data = jsonxox.loads(contents)
|
|
183
|
+
|
|
184
|
+
assert isinstance(data, dict)
|
|
185
|
+
|
|
186
|
+
assert "a" in data
|
|
187
|
+
assert data["a"] == 123
|
|
188
|
+
|
|
189
|
+
assert "b" in data
|
|
190
|
+
assert data["b"] == "456"
|
|
191
|
+
|
|
192
|
+
assert "c" in data
|
|
193
|
+
assert data["c"] == 789.10
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def test_jsonxox_loads_with_all_combined_compacted(read: callable):
|
|
197
|
+
"""Text the jsonxox.loads() method."""
|
|
198
|
+
|
|
199
|
+
contents: str = read("examples/all-combined-compacted.jsonx")
|
|
200
|
+
|
|
201
|
+
assert isinstance(contents, str)
|
|
202
|
+
|
|
203
|
+
data = jsonxox.loads(contents)
|
|
204
|
+
|
|
205
|
+
assert isinstance(data, dict)
|
|
206
|
+
|
|
207
|
+
assert "a" in data
|
|
208
|
+
assert data["a"] == 123
|
|
209
|
+
|
|
210
|
+
assert "b" in data
|
|
211
|
+
assert data["b"] == "456"
|
|
212
|
+
|
|
213
|
+
assert "c" in data
|
|
214
|
+
assert data["c"] == 789.10
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def test_jsonxox_dump(path: callable, read: callable):
|
|
218
|
+
"""Text the jsonxox.dump() method."""
|
|
219
|
+
|
|
220
|
+
data = {
|
|
221
|
+
"a": 123,
|
|
222
|
+
"b": "456",
|
|
223
|
+
"c": 789.10,
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
assert isinstance(data, dict)
|
|
227
|
+
|
|
228
|
+
assert "a" in data
|
|
229
|
+
assert data["a"] == 123
|
|
230
|
+
|
|
231
|
+
assert "b" in data
|
|
232
|
+
assert data["b"] == "456"
|
|
233
|
+
|
|
234
|
+
assert "c" in data
|
|
235
|
+
assert data["c"] == 789.10
|
|
236
|
+
|
|
237
|
+
with io.StringIO() as handle:
|
|
238
|
+
jsonxox.dump(data, handle, indent=2, ensure_ascii=False)
|
|
239
|
+
|
|
240
|
+
handle.seek(0)
|
|
241
|
+
|
|
242
|
+
dumped: str = handle.read()
|
|
243
|
+
|
|
244
|
+
assert isinstance(dumped, str)
|
|
245
|
+
|
|
246
|
+
contents: str = read("examples/dumped.json")
|
|
247
|
+
|
|
248
|
+
assert isinstance(contents, str)
|
|
249
|
+
|
|
250
|
+
assert dumped == contents
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def test_jsonxox_dumps(path: callable, read: callable):
|
|
254
|
+
"""Text the jsonxox.dumps() method."""
|
|
255
|
+
|
|
256
|
+
data = {
|
|
257
|
+
"a": 123,
|
|
258
|
+
"b": "456",
|
|
259
|
+
"c": 789.10,
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
assert isinstance(data, dict)
|
|
263
|
+
|
|
264
|
+
assert "a" in data
|
|
265
|
+
assert data["a"] == 123
|
|
266
|
+
|
|
267
|
+
assert "b" in data
|
|
268
|
+
assert data["b"] == "456"
|
|
269
|
+
|
|
270
|
+
assert "c" in data
|
|
271
|
+
assert data["c"] == 789.10
|
|
272
|
+
|
|
273
|
+
dumped: str = jsonxox.dumps(data, indent=2, ensure_ascii=False)
|
|
274
|
+
|
|
275
|
+
assert isinstance(dumped, str)
|
|
276
|
+
|
|
277
|
+
contents: str = read("examples/dumped.json")
|
|
278
|
+
|
|
279
|
+
assert isinstance(contents, str)
|
|
280
|
+
|
|
281
|
+
assert dumped == contents
|