10
10
Python bindings to the fantastic `yyjson `_ project. This module provides a fast,
11
11
flexible, portable, and correct JSON parser and serializer.
12
12
13
- Binary packages are provided for many versions of Python on many architectures,
14
- and only requires a C89-compliant compiler when building from source.
13
+ .. image :: https://img.shields.io/github/sponsors/tktech
14
+ :alt: GitHub Sponsors
15
15
16
- Sales Pitch
17
- -----------
16
+ .. image :: https://img.shields.io/pypi/l/yyjson
17
+ :alt: PyPI - License
18
18
19
- [py]yyjson is several times faster than the builtin JSON module, and is faster
20
- than most other JSON libraries. It's also more flexible, allowing you to parse
21
- JSON with strict specification compliance, or with extensions such as comments,
22
- trailing commas, Inf/NaN, and more.
19
+ .. image :: https://img.shields.io/pypi/v/yyjson
20
+ :alt: PyPI - Version
23
21
24
- For all Python JSON libraries, the majority of time isn't spent parsing the
25
- JSON, it's spent creating Python objects to represent that JSON. [py]yyjson
26
- can provide significant speedups by avoiding creating Python objects for the
27
- entire document, allowing you to extract just the parts of the document you
28
- actually care about. It also provides facilities for manipulating the
29
- document in native code, such as performing a JSON Merge-Patch (RFC 7386)
30
- or a JSON Patch (RFC 6902), avoiding creating Python objects entirely.
31
22
32
- [py]yyjson is a lightweight project dependency with low maintenance overhead.
33
- It's written in C, and has no dependencies other than a C89 compiler. It's
34
- licensed under the MIT license, so you can use it in any project, even
35
- commercial ones. Pre-built binary wheels are available for many versions of
36
- Python on many architectures, such as x86, x86_64, ARM, and ARM64, PowerPC,
37
- IBM Z, and more. PyPy is also supported.
23
+ Features
24
+ --------
25
+
26
+ - **Fast **: `yyjson ` is several times faster than the builtin JSON module, and
27
+ is `faster than most other JSON libraries <https://github.com/tktech/json_benchmark >`_.
28
+ - **Flexible **: Parse JSON with strict specification compliance, or with
29
+ extensions such as comments, trailing commas, Inf/NaN, numbers of any size,
30
+ and more.
31
+ - **Lightweight **: `yyjson ` is a lightweight project dependency with low
32
+ maintenance overhead. It's written in C, and has no dependencies other than
33
+ a C89 compiler. Built wheels are between 50kb and 800kb depending on the
34
+ platform.
35
+ - **Portable **: Binary wheels are available for many versions of Python
36
+ on many architectures, such as x86, x86_64, ARM, and ARM64, PowerPC, IBM Z,
37
+ and more. PyPy is also supported. Supports Python 3.9 and newer.
38
+ - **Manipulate documents **: The fastest JSON Merge-Patch (RFC 7386), JSON Patch
39
+ (RFC 6902), and JSON Pointer (RFC 6901) implementations available for Python
40
+ allow you to manipulate JSON documents without deserializing them into Python
41
+ objects.
42
+ - **Traceable **: `yyjson ` uses Python's memory allocator by default, so you can
43
+ trace memory leaks and other memory issues using Python's built-in tools.
38
44
39
45
40
46
Installation
41
47
------------
42
48
43
49
If binary wheels are available for your platform, you can install the latest
44
- version of [py] yyjson with pip:
50
+ version of yyjson with pip:
45
51
46
52
pip install yyjson
47
53
48
54
If you want to build from source, or if binary wheels aren't available, you'll
49
- need a C89 compiler, such as GCC or Clang.
55
+ just need a C89 compiler, such as GCC or Clang.
56
+
57
+ Or you can install the latest development version from GitHub:
58
+
59
+ pip install git+https://github.com/tktech/py_yyjson.git
50
60
51
61
52
62
Benchmarks
@@ -59,35 +69,68 @@ libraries.
59
69
Examples
60
70
--------
61
71
62
- Load a document
63
- ^^^^^^^^^^^^^^^
72
+ Parsing
73
+ ^^^^^^^
64
74
65
- Simply parse an entire JSON document to a Python object: :
75
+ Parse a JSON document from a file :
66
76
67
- from pathlib import Path
68
- from yyjson import Document
77
+ .. code-block :: python
78
+
79
+ >> > from pathlib import Path
80
+ >> > from yyjson import Document
81
+ >> > doc = Document(Path(" canada.json" )).as_obj
82
+ >> > doc
83
+ {' type' : ' FeatureCollection' , ' features' : [... ], ' bbox' : [... ], ' crs' : {... }}
84
+
85
+
86
+ Parse a JSON document from a string:
87
+
88
+ .. code-block :: python
69
89
70
- doc = Document(Path("canada.json")).as_obj
90
+ >> > from yyjson import Document
91
+ >> > doc = Document(' {"hello": "world"}' ).as_obj
92
+ >> > doc
93
+ {' hello' : ' world' }
94
+
95
+ Parse a JSON document from a bytes object:
96
+
97
+ .. code-block :: python
98
+
99
+ >> > from yyjson import Document
100
+ >> > doc = Document(b ' {"hello": "world"}' ).as_obj
101
+ >> > doc
102
+ {' hello' : ' world' }
71
103
72
104
73
105
Load part of a document
74
106
^^^^^^^^^^^^^^^^^^^^^^^
75
107
76
- Parse a JSON document, but only extract the part you care about by using
77
- a JSON Pointer::
108
+ When you only need a small part of a document, you can use a JSON Pointer to
109
+ extract just the part you actually need. This can be a massive performance
110
+ improvement when working with large JSON documents, as most of the time
111
+ spent parsing JSON in Python is spent just creating the Python objects!
78
112
79
- from pathlib import Path
80
- from yyjson import Document
113
+ .. code-block :: python
81
114
82
- doc = Document(Path("canada.json"))
83
- features = doc.get_pointer("/features")
115
+ >> from pathlib import Path
116
+ >> from yyjson import Document
117
+ >> > doc = Document(Path(" canada.json" ))
118
+ >> > features = doc.get_pointer(" /features" )
84
119
85
120
86
121
Patch a document
87
122
^^^^^^^^^^^^^^^^
88
123
89
- Add an entry to a GeoJSON file without deserializing the entire document
90
- into Python objects::
124
+ JSON manipulation operations are supported, such as
125
+ `JSON Merge-Patch <https://tools.ietf.org/html/rfc7386 >`_ and
126
+ `JSON Patch <https://tools.ietf.org/html/rfc6902 >`_. These operations
127
+ allow you to manipulate JSON documents without deserializing them into
128
+ Python objects at all.
129
+
130
+ For example, lets add an entry to a GeoJSON file without deserializing
131
+ the entire document into Python objects using JSON Patch:
132
+
133
+ .. code-block :: python
91
134
92
135
from pathlib import Path
93
136
from yyjson import Document
@@ -112,14 +155,83 @@ into Python objects::
112
155
Serialize an object
113
156
^^^^^^^^^^^^^^^^^^^
114
157
115
- Serialize a Python object to JSON::
158
+ Serialize a Python object to JSON :
116
159
117
- from yyjson import Document
160
+ .. code- block:: python
161
+
162
+ >> > from yyjson import Document
163
+ >> > doc = Document({
164
+ ... " hello" : " world" ,
165
+ ... " foo" : [1 , 2 , 3 ],
166
+ ... " bar" : {" a" : 1 , " b" : 2 }
167
+ ... })
168
+ >> > doc.dumps()
169
+ ' {"hello":"world","foo":[1,2,3],"bar":{"a":1,"b":2}} '
170
+
171
+
172
+ Customizing JSON Reading & Writing
173
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
174
+
175
+ You can customize the JSON reading and writing process using
176
+ :class :`yyjson.ReaderFlags` and :class :`yyjson.WriterFlags` . For example
177
+ if we wanted to allow comments and trailing commas, we could do:
178
+
179
+
180
+ .. code- block:: python
181
+
182
+ >> > from yyjson import Document, ReaderFlags, WriterFlags
183
+ >> > doc = Document(
184
+ ... ' {"hello": "world",} // This is a comment' ,
185
+ ... ReaderFlags.ALLOW_COMMENTS | ReaderFlags.ALLOW_TRAILING_COMMAS
186
+ ... )
187
+
188
+
189
+ Likewise we can customize the writing process:
190
+
191
+
192
+ .. code- block:: python
193
+
194
+ >> > from yyjson import Document, ReaderFlags, WriterFlags
195
+ >> > doc = Document({
196
+ ... " hello" : " world"
197
+ ... })
198
+ >> > doc.dumps(flags = WriterFlags.PRETTY_TWO_SPACES )
199
+
200
+
201
+ Reading Huge Numbers
202
+ ^^^^^^^^^^^^^^^^^^^^
203
+
204
+ If you' re reading huge floats/doubles or require perfect precision, you can
205
+ tell yyjson to read them as Decimals:
206
+
207
+ .. code- block:: python
208
+
209
+ >> > from yyjson import Document, ReaderFlags
210
+ >> > float (' 1.7976931348623157e+310' )
211
+ inf
212
+ >> > doc = Document(
213
+ ... ' {"huge": 1.7976931348623157e+310}' ,
214
+ ... flags = ReaderFlags.NUMBERS_AS_DECIMAL
215
+ ... )
216
+ >> > print (doc.get_pointer(' /huge' ))
217
+ 1.7976931348623157E+310
218
+
219
+
220
+ Or use `` ReaderFlags.BIG_NUMBERS_AS_DECIMAL `` to only read numbers that are
221
+ too large for Python' s float type as Decimals:
222
+
223
+ .. code- block:: python
224
+
225
+ >> > from yyjson import Document, ReaderFlags
226
+ >> > doc = Document(
227
+ ' {"huge": 1.7976931348623157e+310, "small": 1.0}' ,
228
+ flags = ReaderFlags.BIG_NUMBERS_AS_DECIMAL
229
+ )
230
+ >> > type (doc.get_pointer(' /huge' ))
231
+ < class ' decimal.Decimal' >
232
+ >> > type (doc.get_pointer(' /small' ))
233
+ < class ' float' >
118
234
119
- doc = Document({
120
- "hello": "world"
121
- })
122
- print(doc.dumps())
123
235
124
236
.. _yyjson: https:// github.com/ ibireme/ yyjson
125
237
.. _json_benchmark: https:// github.com/ tktech/ json_benchmark
0 commit comments