Skip to main content
drawing

jsonbourne

Wheel Version py_versions Ruff

Install: pip install jsonbourne

  • Python json lib/pkg that makes json feel like the JSON module in javascript/typescript:
    • from jsonbourne import JSON; JSON.parse(JSON.stringify({"key": "value"}))
    • Automatically uses best json-lib-backend available (orjson/python-rapidjson) ~ can be configured
  • Hybrid dict/class object (jsonbourne.JsonObj):
    • Dot-notation getting/setting (featuring protected attributes!)
    • All your favorite python dictionary methods (items, keys, update, values) and more!
    • Works with pydantic and attrs
  • FastAPI:
    • JSONBOURNEResponse ~ auto use the best
  • No hard dependencies ~ works with python-stdlib-json as well as orjson and python-rapidjson
  • jsonbourne.JsonObj uses list/dict comprehensions (some are recursive) everywhere because 'why not?' and it is a bit faster

Usage:

JSON ~ from jsonbourne import JSON

Importing:

# Importing JSON:
from jsonbourne import JSON

# or
import JSON

# Importing jsonbourne:
import jsonbourne
import david_webb  # jsonbourne's `True` identity

JSON basics:

import JSON  # Module included with jsonbourne

string_stringify = JSON.stringify(
    {"a": 1, "b": 2, "c": 3}
)  # '{"a": 1, "b": 2, "c": 3}'
string_dumps = JSON.dumps({"a": 1, "b": 2, "c": 3})  # '{"a": 1, "b": 2, "c": 3}'
string_dumps
'{"a":1,"b":2,"c":3}'

JSON option kwargs ~ pretty & sort_keys

pretty:

string_dumps = JSON.stringify(
    {"b": 2, "a": 1, "c": 3}, pretty=True
)  # '{"a": 1, "b": 2, "c": 3}'
print(string_dumps)
{
  "b": 2,
  "a": 1,
  "c": 3
}

sort_keys:

string_dumps = JSON.stringify(
    {"b": 2, "a": 1, "c": 3}, pretty=True, sort_keys=True
)  # '{"a": 1, "b": 2, "c": 3}'
print(string_dumps)
{
  "a": 1,
  "b": 2,
  "c": 3
}

JsonObj & JSON

  • Python dictionary/object with dot access
  • Protections against setting class/obj attributes
  • Is as javascript-y as possible (keys have to be strings -- ints/floats will be converted to strings)
  • Create a jsonbourne.JsonObj with jsonbourne.JSON
  • Recursive jsonification
  • Allows for kwarging (**json_obj)
  • Works with pydantic and attrs

Make an empty JsonObj

The following 3 examples all produce the same thing

from jsonbourne import JSON
j = JSON()  # j => JsonObj(**{})
# OR
import JSON
j = JSON()  # j => JsonObj(**{})
# OR
from jsonbourne import JsonObj
j = JsonObj()  # j => JsonObj(**{})

From a dictionary o data

import datetime

data = {
    "key": "value",
    "list": [1, 2, 3, 4, 5],
    "dt": datetime.datetime(1970, 1, 1, 0, 0, 0, 1),
    "sub": {
        "b": 3,
        "key": "val",
        "a": 1,
    },
    "timedelta": datetime.timedelta(days=2),
}

JSON(data)
JsonObj(**{
    'dt': datetime.datetime(1970, 1, 1, 0, 0, 0, 1),
    'key': 'value',
    'list': [1, 2, 3, 4, 5],
    'sub': {'a': 1, 'b': 3, 'key': 'val'},
    'timedelta': datetime.timedelta(days=2)
})

Dot access

JSON(data).sub.b
3
stringified_data = JSON(data).stringify(pretty=True)
print(stringified_data)
{
  "key": "value",
  "list": [
    1,
    2,
    3,
    4,
    5
  ],
  "dt": "1970-01-01T00:00:00.000001",
  "sub": {
    "b": 3,
    "key": "val",
    "a": 1
  },
  "timedelta": 172800.0
}
parsed_data = JSON(stringified_data)
parsed_data
JsonObj(**{
    'dt': '1970-01-01T00:00:00.000001',
    'key': 'value',
    'list': [1, 2, 3, 4, 5],
    'sub': {'a': 1, 'b': 3, 'key': 'val'},
    'timedelta': 172800.0
})
list(parsed_data.keys())
['key', 'list', 'dt', 'sub', 'timedelta']
list(parsed_data.items())
[('key', 'value'),
 ('list', [1, 2, 3, 4, 5]),
 ('dt', '1970-01-01T00:00:00.000001'),
 ('sub', JsonObj(**{'b': 3, 'key': 'val', 'a': 1})),
 ('timedelta', 172800.0)]
list(parsed_data.dot_keys())
[('key',),
 ('list',),
 ('dt',),
 ('sub', 'b'),
 ('sub', 'key'),
 ('sub', 'a'),
 ('timedelta',)]
list(parsed_data.dot_items())
[(('key',), 'value'),
 (('list',), [1, 2, 3, 4, 5]),
 (('dt',), '1970-01-01T00:00:00.000001'),
 (('sub', 'b'), 3),
 (('sub', 'key'), 'val'),
 (('sub', 'a'), 1),
 (('timedelta',), 172800.0)]
parsed_data[("sub", "key")]
'val'
parsed_data.dot_lookup("sub.key")
'val'
{**parsed_data}
{'key': 'value',
 'list': [1, 2, 3, 4, 5],
 'dt': '1970-01-01T00:00:00.000001',
 'sub': JsonObj(**{'b': 3, 'key': 'val', 'a': 1}),
 'timedelta': 172800.0}
# fully eject
parsed_data.eject()
{'key': 'value',
 'list': [1, 2, 3, 4, 5],
 'dt': '1970-01-01T00:00:00.000001',
 'sub': {'b': 3, 'key': 'val', 'a': 1},
 'timedelta': 172800.0}

Protected keys

jsonbourne.JsonObj protects against setting attributes like 'items' through dot-notation.

from jsonbourne import JSON

j = JSON()
j.key = "value"
try:  # CANNOT set 'items' using dot-access
    j.items = [1, 2, 3, 4]
except ValueError:
    ...
# CAN set 'items' through key/item access
j["items"] = [1, 2, 3, 4]
print(j.__dict__)
print(j)
j_items = j.items
print("items", j_items)
# Getting 'items' through dot-access returns the `items()` method
assert j.items != [1, 2, 3, 4]
# Getting 'items' with key-access returns the stored value
assert j["items"] == [1, 2, 3, 4]
{'_data': {'key': 'value', 'items': [1, 2, 3, 4]}}
JsonObj(**{
    'items': [1, 2, 3, 4], 'key': 'value'
})
items <bound method JsonObj.items of JsonObj(**{'key': 'value', 'items': [1, 2, 3, 4]})>

pydantic & jsonbourne

  • from jsonbourne.pydantic import JsonBaseModel
  • Allows for aliases when getting/setting attribute(s)
  • Supports __post_init__ (like dataclasses)

Basic usage:

from jsonbourne import JsonObj
from jsonbourne.pydantic import JsonBaseModel


class JsonSubObj(JsonBaseModel):
    herm: int

    def to_dict(self):
        return self.dict()

    def to_json(self, *args, **kwargs):
        return self.json()

    @classmethod
    def from_json(cls, json_string: str):
        return JsonSubObj(json.loads(json_string))


class JsonObjModel(JsonBaseModel):
    a: int
    b: int
    c: str
    d: JsonObj
    e: JsonSubObj

    #
    @property
    def a_property(self) -> str:
        return "prop_value"

    def to_json(self, *args, **kwargs):
        return self.json()

    @classmethod
    def from_json(cls, json_string: str):
        return cls(**json.loads(json_string))


obj = JsonObjModel(
    **{"a": 1, "b": 2, "c": "herm", "d": {"nested": "nestedval"}, "e": {"herm": 2}}
)
obj
JsonObjModel(**{
     'a': 1,
     'b': 2,
     'c': 'herm',
     'd': JsonObj(**{'nested': 'nestedval'}),
     'e': {'herm': 2}
})
# respects properties (which I don't think pydantic does(currently))
obj.a_property
'prop_value'

JSON backend/lib

jsonbourne finds the best json-lib (python-rapidjson/orjson) it can! On import jsonbourne gets to work spying on your python env. jsonbourne, the most highly qualified json-CIA-agent, will import the best python-json library it can find; if jsonbourne's cover is blown (meaning: the only json library found is the python stdlib json), jsonbourne will fallback to the python stdlib json.

jsonbourne will look for the following json-packages in the following order:

  1. rapidjson
  2. orjson

Custom lib preferences

from jsonbourne import import_json

json = import_json(("rapidjson", "orjson"))  # prefer rapidjson over orjson
string = json.dumps({"a": 1, "b": 2, "c": 3})
print(json)
print(string)
<class 'jsonbourne.jsonlib.RAPIDJSON'>
{"a":1,"b":2,"c":3}

Installing better JSON lib:

orjson

  • pip install orjson [pip]

rapidjson/python-rapidjson

  • pip install python-rapidjson [pip]
  • conda install -c anaconda python-rapidjson [conda anaconda/defaults]
  • conda install -c conda-forge python-rapidjson [conda-forge]

Metadata

Release files for jsonbourne 0.32.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jsonbourne 0.32.1
File Size Uploaded
jsonbourne-0.32.1.tar.gz 21.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jsonbourne 0.32.1
File Interpreter ABI Platform
jsonbourne-0.32.1-py3-none-any.whl Python 3 none any Details

Total release size: 46.9 kB

Release files / jsonbourne-0.32.1.tar.gz

Download URL jsonbourne-0.32.1.tar.gz
Size 21.3 kB
Tags Source
SHA-256 checksum
How to use checksums
027a7a968c3c68702103766c6757ca0f58349e58bc087bb526f556bf0cfda062
BLAKE2b-256 checksum
How to use checksums
fccff0bb2a060d6c687c27e1ee6f3021cbaaae613548ebc67cd2a0b2b623de90
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.1

Release files / jsonbourne-0.32.1-py3-none-any.whl

Download URL jsonbourne-0.32.1-py3-none-any.whl
Size 25.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7247784094a843f4fb622ec6c7f8cd2fa04f15c29aeb20d95b75302541da4d62
BLAKE2b-256 checksum
How to use checksums
40a17ff1872d2c1a706ca6656955b6f082574a514b039f1e0ad96d7fb1019013
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.1

Release history Release notifications | RSS feed

This release

0.32.1 This release

2 release files

0.32.0

2 release files

0.31.1

2 release files

0.27.0

2 release files

0.25.2

2 release files

0.25.1

2 release files

0.25.0

2 release files

0.22.2

2 release files

0.22.0

2 release files

0.21.6

2 release files

0.21.5

2 release files

0.20.3

2 release files

0.20.2

2 release files

0.20.1

2 release files

0.17.1

2 release files

0.17.0

2 release files

0.16.0

2 release files

0.15.1

2 release files

0.15.0

2 release files

0.14.4

2 release files

0.14.3

2 release files

0.14.2

2 release files

0.14.1

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page