Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
spyoungtech committed Aug 1, 2023
1 parent 327837f commit 466c5c2
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 21 deletions.
134 changes: 115 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,142 @@
JSON5 for Python

[![Documentation Status](https://readthedocs.org/projects/json-five/badge/?version=latest)](https://json-five.readthedocs.io/en/latest/?badge=latest)
[![Build Status](https://travis-ci.com/spyoungtech/json-five.svg?branch=master)](https://travis-ci.com/spyoungtech/json-five)
[![Build](https://github.com/spyoungtech/json-five/actions/workflows/unittests.yml/badge.svg)](https://github.com/spyoungtech/json-five/actions/workflows/unittests.yaml)
[![version](https://img.shields.io/pypi/v/json-five.svg?colorB=blue)](https://pypi.org/project/json-five/)
[![pyversion](https://img.shields.io/pypi/pyversions/json-five.svg?)](https://pypi.org/project/json-five/)
[![Coverage](https://coveralls.io/repos/github/spyoungtech/json-five/badge.svg?branch=master)](https://coveralls.io/github/spyoungtech/json-five?branch=master)
[![Coverage](https://coveralls.io/repos/github/spyoungtech/json-five/badge.svg?branch=main)](https://coveralls.io/github/spyoungtech/json-five?branch=main)

## Installation

```
pip install json-five
```

This project requires Python 3.6 or newer.
This project requires Python 3.8+

## Usage

**NOTE:** the import name is different from the install name (sorry, many were taken already)
## Key features

- Supports the JSON5 spec
- Supports similar interfaces to stdlib `json` module
- Provides an API for working with abstract model representations of JSON5 documents.
- Supports round-trip loading, editing, and dumping, preserving non-data elements such as comments (in model-based load/dump)



# Usage

**NOTE:** the import name is `json5` which differs from the install name.


For basic loading/dumping, the interface is nearly identical to that of the `json` module.
```python
>>> import json5
>>> json_text = """{ // This is a JSON5 comment
import json5
json_text = """{ // This is a JSON5 comment
"foo": "bar" /* this is a JSON5 block
comment that can span lines /*
"bacon": "eggs"
bacon: "eggs" // unquoted Identifiers also work
}
"""
>>> json5.loads(json_text)
{"foo": "bar", "bacon": "eggs"}
print(json5.loads(json_text))
# {"foo": "bar", "bacon": "eggs"}

with open('myfile.json5') as f:
data = json5.load(f)
```

See also the [full documentation](https://json-five.readthedocs.io/en/latest/)
For loading JSON5, the same parameters `object_hook`, `object_pairs_hook` and `parse_*` keyword arguments are available
here for `load`/`loads`.

## Key features
Additionally, a new hook, `parse_json5_identifiers`, is available to help users control the
output of parsing identifiers. By default, JSON5 Identifiers in object keys are returned as a `JsonIdentifier` object,
which is a subclass of `str` (meaning it's compatible anywhere `str` is accepted).
This helps keep keys the same round-trip, rather than converting unquoted identifiers into
strings:

- Supports the JSON5 spec
- Supports similar interfaces to stdlib `json` module
- Supports round-trip preservation of comments
- Tries to find _all_ syntax errors at once (instead of raising on the first error encountered)
```python
>>> text = '{bacon: "eggs"}'
>>> json5.dumps(json5.loads(text)) == text
True
```

You can change this behavior with the `parse_json5_identifiers` argument with a callable that receives the `JsonIdentifier` object
and its return value is used instead. For example, you can specify `parse_json5_identifiers=str` to convert identifiers
to strings.

```python
>>> json5.dumps(json5.loads(text, parse_json5_identifiers=str))
'{"bacon": "eggs"}'
```


## Custom loaders; Abstract JSON5 Models

**Note:** the underlying model API and tokens are not stable and are subject to breaking changes, even in minor releases.

json-five also features an API for representing JSON5 as an abstract model. This enables a wide degree of capabilities for
various use-cases, such as linters, formatters, custom serialization/deserialization, and more.


Example: a simple model

```python
from json5.loader import loads, ModelLoader
json_string = """{"foo": "bar"}"""
model = loads(json_string, loader=ModelLoader())
```
The model object looks something like this:
```python
JSONText(
value=JSONObject(
key_value_pairs=[
KeyValuePair(
key=DoubleQuotedString(
characters="foo",
raw_value='"foo"',
tok=JSON5Token(
type="DOUBLE_QUOTE_STRING",
value='"foo"',
lineno=1,
index=1,
end=None,
),
),
value=DoubleQuotedString(
characters="bar",
raw_value='"bar"',
tok=JSON5Token(
type="DOUBLE_QUOTE_STRING",
value='"bar"',
lineno=1,
index=8,
end=None,
),
),
tok=JSON5Token(
type="DOUBLE_QUOTE_STRING",
value='"foo"',
lineno=1,
index=1,
end=None,
),
)
],
trailing_comma=None,
)
)
```


It is possible to make edits to the model, which will affect the output when dumped using the model dumper. However,
there is (currently) no validation to ensure your model edits won't result in invalid JSON5 when dumped.

You may also implement custom loaders and dumpers to control serialization and deserialization. See the [full documentation](https://json-five.readthedocs.io/en/latest/extending.html#custom-loaders-and-dumpers)
for more information.


## Status
# Status

This project currently fully supports the JSON5 spec but is still undergoing active development, particularly for round-trip support and model-level edits. Additional features are still being added. Check the [issues](https://github.com/spyoungtech/json-five/issues)
page to see known bugs and unimplemented features.
This project currently fully supports the JSON5 spec and its interfaces for loading and dumping JSON5 is stable as of v1.0.0.
There is still active development underway, particularly for the underlying abstract JSON5 model representations and
ability to perform edits using the abstract model.
14 changes: 12 additions & 2 deletions docs/extending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,18 @@ you can provide the following arguments that have the same meaning as in ``json.
This is convenient if you have existing code that uses these arguments with the ``json`` module, but want to also
support JSON5. These options are also useful as a simple way to customize parsing of json types.

However, this package does not support the ``cls`` keyword. If you want to implement custom serializers/deserializers,
read on about custom loaders/dumpers
Additionally, a new hook keyword argument, ``parse_json5_identifiers``, is available to help users control the
output of parsing identifiers. By default, JSON5 Identifiers in object keys are returned as a ``JsonIdentifier`` object,
which is a subclass of ``str`` (meaning it's compatible anywhere ``str`` is accepted).
This helps keep keys the same round-trip, rather than converting unquoted identifiers into quoted strings, such that
``dumps(loads(text)) == text`` (in this case).

You can change this behavior with the ``parse_json5_identifiers`` keyword argument with a callable that receives the `JsonIdentifier` object
and its return value is used instead. For example, you can specify ``parse_json5_identifiers=str`` to convert identifiers
to normal strings, such that ``dumps(loads('{foo: "bar"}')) == '{"foo": "bar"}'``.

However, this package does not support the ``cls`` keyword found in the standard library ``json`` module.
If you want to implement custom serializers/deserializers, read on about custom loaders/dumpers.


Custom Loaders and Dumpers
Expand Down

0 comments on commit 466c5c2

Please sign in to comment.