Skip to content

Commit eba010c

Browse files
committed
Added full API docs and command-line
1 parent 314757b commit eba010c

1 file changed

Lines changed: 212 additions & 17 deletions

File tree

README.md

Lines changed: 212 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,227 @@
11
# fractured-json
22

3-
[![build:](https://github.com/masaccio/fractured-json/actions/workflows/run-all-tests.yml/badge.svg)](https://github.com/masaccio/fractured-json/actions/workflows/run-all-tests.yml)
4-
[![build:](https://github.com/masaccio/fractured-json/actions/workflows/codeql.yml/badge.svg)](https://github.com/masaccio/fractured-json/actions/workflows/codeql.yml)
5-
[![codecov](https://codecov.io/gh/masaccio/fractured-json/branch/main/graph/badge.svg?token=EKIUFGT05E)](https://codecov.io/gh/masaccio/fractured-json)
3+
[![build:](https://github.com/masaccio/fractured-json-python/actions/workflows/run-all-tests.yml/badge.svg)](https://github.com/masaccio/fractured-json-python/actions/workflows/run-all-tests.yml)
64

5+
[![build:](https://github.com/masaccio/fractured-json-python/actions/workflows/codeql.yml/badge.svg)](https://github.com/masaccio/fractured-json-python/actions/workflows/codeql.yml)
6+
[![codecov](https://codecov.io/gh/masaccio/fractured-json-python/branch/main/graph/badge.svg?token=EKIUFGT05E)](https://codecov.io/gh/masaccio/fractured-json-python)
77

8-
`fractured-json` is primarily a python wrapper of of [FracturedJson](https://github.com/j-brooke/FracturedJson) by [j-brooke](https://github.com/j-brooke).
8+
`fractured-json` is a python wrapper of [FracturedJson](https://github.com/j-brooke/FracturedJson) by [j-brooke](https://github.com/j-brooke). The package fully follows the .NET version and includes the required assembly to run as long as you have installed a suitabe .NET runtime.
99

10-
There is a pure Python implementation of a JSON compactor called [`compact-json`](https://github.com/masaccio/compact-json) however this is unlikely to get maintenance beyond critical bugfixes.
10+
## Installation
1111

12-
## Plans
12+
You must install a valid .NET runtime that is compatible with [Python.NET](https://pythonnet.github.io) (`pythonnet`). The package honors the environment variable `PYTHONNET_RUNTIME` for selecting the runtime variant but defaults to `coreclr`. As of current testing, Python versions 3.11 through 3.12 and .NET versions 7.0 and 8.0 are supported. Later versions are currently not supported by `pythonnet`.
1313

14-
**THE PACKAGE IS CURRENTLY UNDER DEVELOPMENT**
14+
You can download the Core .NET runtime from the [Microsoft .NET website](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) and version 8.0 is recommended as the stable and long-term supported version. Once installed, installation is simply:
1515

16-
Feel free to [join the discussion about the python wrapper](https://github.com/j-brooke/FracturedJson/discussions/48). The goal of the python wrapper is to track the .NET core of the JSON formatter and provide all the features of the .NET version in python. The command-line capabilities of `compact-json` and the FracturedJson CLI are expected to merge.
16+
``` shell
17+
python3 -m pip install fractured-json
18+
```
1719

18-
The API naming style of the python implementation is deliberately different to the .NET core to be as pythonic as possible. Specifically:
20+
There is a pure Python implementation of a JSON compactor called [`compact-json`](https://github.com/masaccio/compact-json) however this has now been archived on PyPI and will receive no further development.
21+
22+
The [FracturedJson Wiki](https://github.com/j-brooke/FracturedJson/wiki) provides full documentation of intent, and a description of the options. This README is untended to cover only the Python specific elements of the wrapper.
23+
24+
## Command-line
25+
26+
The package installs a command-line script `fractured-json` which can compact one or more JSON files according to command-line switches.
27+
28+
```bash
29+
usage: fractured-json [-h] [-V] [--output OUTPUT]
30+
[--allow-trailing-commas] [--always-expand-depth N]
31+
[--colon-before-prop-name-padding] [--colon-padding]
32+
[--comma-padding] [--comment-padding]
33+
[--comment-policy {TREAT_AS_ERROR,REMOVE,PRESERVE}]
34+
[--indent-spaces N]
35+
[--json-eol-style {DEFAULT,CRLF,LF}]
36+
[--max-compact-array-complexity N]
37+
[--max-inline-complexity N]
38+
[--max-prop-name-padding N]
39+
[--max-table-row-complexity N]
40+
[--max-total-line-length N]
41+
[--min-compact-array-row-items N]
42+
[--nested-bracket-padding]
43+
[--number-list-alignment {LEFT,RIGHT,DECIMAL,NORMALIZE}]
44+
[--prefix-string PREFIX_STRING]
45+
[--preserve-blank-lines] [--simple-bracket-padding]
46+
[--table-comma-placement {BEFORE_PADDING,AFTER_PADDING,BEFORE_PADDING_EXCEPT_NUMBERS}]
47+
[--use-tab-to-indent] [--east-asian-chars]
48+
[json ...]
49+
50+
Format JSON into compact, human readable form
51+
52+
positional arguments:
53+
json JSON file(s) to parse (or stdin with "-")
54+
55+
options:
56+
-h, --help show this help message and exit
57+
-V, --version
58+
--output, -o OUTPUT The output file name(s). The number of output file
59+
names must match the number of input files.
60+
--allow-trailing-commas
61+
If true, the final element in an array or object
62+
in the input may have a comma after it; otherwise
63+
an exception is thrown. The JSON standard doesn't
64+
allow trailing commas, but some other tools allow
65+
them, so the option is provided for
66+
interoperability with them. (default=False)
67+
--always-expand-depth N
68+
Forces elements close to the root to always fully
69+
expand, regardless of other settings. (default=-1)
70+
--colon-before-prop-name-padding
71+
Set to true if you want colons to the left of the
72+
spaces uses to line up expanded properties. false
73+
puts them after the padding, in a row of their
74+
own. (default=False)
75+
--colon-padding If true, a space is added after a colon.
76+
(default=True)
77+
--comma-padding If true, a space is added after a comma.
78+
(default=True)
79+
--comment-padding If true, a space is added between a prefix/postfix
80+
comment and the element to which it is attached.
81+
(default=True)
82+
--comment-policy {TREAT_AS_ERROR,REMOVE,PRESERVE}
83+
Determines how comments should be handled. The
84+
JSON standard doesn't allow comments, but as an
85+
unofficial extension they are fairly wide-spread
86+
and useful. (default=TREAT_AS_ERROR)
87+
--indent-spaces N Indents by this number of spaces for each level of
88+
depth. If use-tab-to-indent=true , tab characters
89+
will be used instead of spaces, but the indent-
90+
spaces value will still be used to calculate line
91+
lengths. (default=4)
92+
--json-eol-style {DEFAULT,CRLF,LF}
93+
Determines which sort of line endings to use.
94+
(default=DEFAULT)
95+
--max-compact-array-complexity N
96+
Maximum nesting level that can be arranged
97+
spanning multiple lines, with multiple items per
98+
line. (default=2)
99+
--max-inline-complexity N
100+
The maximum nesting level that can be displayed on
101+
a single line. A primitive type or an empty array
102+
or object has a complexity of 0. An object or
103+
array has a complexity of 1 greater than its most
104+
complex child. (default=2)
105+
--max-prop-name-padding N
106+
Expanded object property values will be lined up
107+
as long as the size difference in labels is this
108+
value or less. Generally, lining up the property
109+
values looks good as long as the labels are
110+
roughly the same size, but not if they vary a lot.
111+
This only applies to expanded objects; table
112+
properties are lined up no matter what.
113+
(default=16)
114+
--max-table-row-complexity N
115+
Maximum nesting level allowed in a row of a table-
116+
formatted array/object. (default=2)
117+
--max-total-line-length N
118+
Maximum length of a line, including indentation
119+
and everything, for purposes of deciding how much
120+
to pile together. (default=120)
121+
--min-compact-array-row-items N
122+
Minimum number of items per line to be eligible
123+
for compact-multiline-array formatting.
124+
(default=3)
125+
--nested-bracket-padding
126+
If true, a space is added between an
127+
array/object's brackets and its contents, if that
128+
array/object has a complexity of 2 or more. That
129+
is, if it contains non-empty arrays/objects.
130+
(default=True)
131+
--number-list-alignment {LEFT,RIGHT,DECIMAL,NORMALIZE}
132+
Controls how lists or table columns that contain
133+
only numbers and nulls are aligned. In all cases
134+
other than Normalize , numbers in the output are
135+
exactly the same as in the input document. In all
136+
cases, values too big to fit into a 64-bit float
137+
or integer are preserved without issue.
138+
(default=DECIMAL)
139+
--prefix-string PREFIX_STRING
140+
A string to be included at the start of every line
141+
of output. Note that if this string is anything
142+
other than whitespace, it will probably make the
143+
output invalid as JSON. (default=)
144+
--preserve-blank-lines
145+
If true, blank lines (default=False)
146+
--simple-bracket-padding
147+
If true, a space is added between an
148+
array/object's brackets and its contents, if that
149+
array/object has a complexity of 1. That is, if it
150+
only contains primitive elements and/or empty
151+
arrays/objects. (default=False)
152+
--table-comma-placement {BEFORE_PADDING,AFTER_PADDING,BEFORE_PADDING_EXCEPT_NUMBERS}
153+
Where to place commas in table-formatted elements.
154+
(default=BEFORE_PADDING_EXCEPT_NUMBERS)
155+
--use-tab-to-indent If true, a single tab character is used per
156+
indentation level, instead of spaces.
157+
(default=False)
158+
--east-asian-chars Treat strings as unicode East Asian characters
159+
```
19160
20-
* All classes are Pascal case, e.g. FracturedJsonOptions
21-
* All properties are snake case, e.g. json_eol_style
22-
* All enumerations are upper-case snake case within a Python Object, e.g. EolStyle.CRLF. They are not derived from `Enum` but have the same behaviors.
161+
The option `--east-asian-chars` indicates that `fractured-json` should take account of variable width East-Asian character sets when reformatting JSON.
23162
24-
## Installation
163+
Multiple files and output files can be processed at once but the number of input and output files must match:
25164
26-
You will need to install a .NET runtime that is compatible with [Python.NET](https://pythonnet.github.io) (`pythonnet`). The package honors the environment variable `PYTHONNET_RUNTIME` for selecting the runtime variant but defaults to `coreclr`. As of current testing, Python 3.14 and .NET 10.0 are not supported by `pythonnet`. You can download the Core .NET runtime from the [Microsoft .NET website](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) and version 8.0 is recommended as the stable and long-term supported version.
165+
``` bash
166+
fractured-json --output new_json_1.json --output new_json_2.json json_1.json json_2.json
167+
```
27168
28-
Once .NET is available, installation is simply:
169+
## API Usage
29170
30-
``` shell
31-
python3 -m pip install fractured-json
171+
Follow the following steps to reformat JSON strings:
172+
173+
* Optionally configure settings using a `fractured_json.FracturedJsonOptions` instance
174+
* Instantiate an instance of `fractured_json.Formatter`
175+
* Call `Formatter.reformat()`.
176+
177+
Example:
178+
179+
``` python
180+
>>> from fractured_json import Formatter, FracturedJsonOptions
181+
>>> options = FracturedJsonOptions(indent_spaces=4)
182+
>>> formatter = Formatter(options)
183+
>>> formatter.reformat('{"a":1}')
184+
'{"a": 1}\n'
185+
```
186+
187+
### Options
188+
189+
A full description of the options available can be found in the [FracturedJson Wiki](https://github.com/j-brooke/FracturedJson/wiki/Options) and these are dynamically created from the .NET library so will always match the .NET implementation.
190+
191+
``` python
192+
from fractured_json import Formatter, FracturedJsonOptions, CommentPolicy
193+
from pathlib import Path
194+
195+
options = FracturedJsonOptions(
196+
allow_trailing_commas=True,
197+
always_expand_depth=2,
198+
colon_before_prop_name_padding=True,
199+
comment_policy=CommentPolicy.PRESERVE
200+
indent_spaces=2,
201+
)
202+
formatter = Formatter(options=options)
203+
json_input = Path("example.jsonc").read_text()
204+
json_output = formatter.reformat(json_input)
205+
```
206+
207+
Enumerations can be passed to `FracturedJsonOptions` as strings or as Python-style enums:
208+
209+
``` python
210+
>>> from fractured_json import NumberListAlignment
211+
>>> FracturedJsonOptions(number_list_alignment=NumberListAlignment.LEFT)
212+
<fractured_json.FracturedJsonOptions object at 0x10966fc50>
213+
>>> FracturedJsonOptions(number_list_alignment="LEFT")
214+
<fractured_json.FracturedJsonOptions object at 0x10966f9d0>
215+
```
216+
217+
### Wide character support
218+
219+
When formatting dictionaries, FracturedJson needs to know the length of strings and for some East-Asian characters, the rendering width needs to be adjusted. The `Formatter.string_length_func` property is used to specify an alternative function to calculate strings lengths. The easiest approach is to use `wcwidth.wcswidth` which is packaged with `fractured-json` as a dependency:
220+
221+
``` python
222+
options = FracturedJsonOptions()
223+
formatter = Formatter(options=options)
224+
formatter.string_length_func = lambda s: wcswidth(s)
32225
```
33226
34227
## License
@@ -38,3 +231,5 @@ All code in this repository is licensed under the [MIT License](https://github.c
38231
## Contribute
39232
40233
Contributions are greatly appreciated and welcomed. Please follow the [project guidance](CONTRIBUTING.md) on how to contribute.
234+
235+
Feel free to [join the discussion about the python wrapper](https://github.com/j-brooke/FracturedJson/discussions/48). The goal of the python wrapper is to track the .NET core of the JSON formatter and provide all the features of the .NET version in python.

0 commit comments

Comments
 (0)