├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── labels.yml ├── release-drafter.yml ├── renovate.json ├── workflows │ ├── benchmark.yml │ ├── deploy.yml │ ├── fuzz.yml │ ├── labels.yml │ ├── lint.yml │ ├── release-drafter.yml │ ├── require-pr-label.yml │ └── test.yml └── zizmor.yml ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── RELEASING.md ├── commits.txt ├── deps └── double-conversion │ ├── .gitignore │ ├── AUTHORS │ ├── BUILD │ ├── CMakeLists.txt │ ├── COPYING │ ├── Changelog │ ├── LICENSE │ ├── README.md │ ├── SConstruct │ ├── WORKSPACE │ ├── cmake │ └── Config.cmake.in │ ├── double-conversion │ ├── .gitignore │ ├── SConscript │ ├── bignum-dtoa.cc │ ├── bignum-dtoa.h │ ├── bignum.cc │ ├── bignum.h │ ├── cached-powers.cc │ ├── cached-powers.h │ ├── diy-fp.h │ ├── double-conversion.h │ ├── double-to-string.cc │ ├── double-to-string.h │ ├── fast-dtoa.cc │ ├── fast-dtoa.h │ ├── fixed-dtoa.cc │ ├── fixed-dtoa.h │ ├── ieee.h │ ├── string-to-double.cc │ ├── string-to-double.h │ ├── strtod.cc │ ├── strtod.h │ └── utils.h │ ├── msvc │ ├── double-conversion.sln │ ├── double-conversion.vcxproj │ ├── double-conversion.vcxproj.filters │ ├── run_tests │ │ ├── run_tests.vcxproj │ │ └── run_tests.vcxproj.filters │ └── testrunner.cmd │ └── test │ ├── CMakeLists.txt │ └── cctest │ ├── CMakeLists.txt │ ├── SConscript │ ├── cctest.cc │ ├── cctest.h │ ├── checks.h │ ├── gay-fixed.cc │ ├── gay-fixed.h │ ├── gay-precision.cc │ ├── gay-precision.h │ ├── gay-shortest-single.cc │ ├── gay-shortest-single.h │ ├── gay-shortest.cc │ ├── gay-shortest.h │ ├── test-bignum-dtoa.cc │ ├── test-bignum.cc │ ├── test-conversions.cc │ ├── test-diy-fp.cc │ ├── test-dtoa.cc │ ├── test-fast-dtoa.cc │ ├── test-fixed-dtoa.cc │ ├── test-ieee.cc │ └── test-strtod.cc ├── pyproject.toml ├── python ├── JSONtoObj.c ├── objToJSON.c ├── ujson.c ├── ujson.h └── version_template.h ├── scripts └── coverage.sh ├── setup.cfg ├── setup.py └── tests ├── 334-reproducer.json ├── benchmark.py ├── fuzz.py ├── memory.py ├── sample.json └── test_ujson.py /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### What did you do? 2 | 3 | ### What did you expect to happen? 4 | 5 | ### What actually happened? 6 | 7 | ### What versions are you using? 8 | 9 | * OS: 10 | * Python: 11 | * UltraJSON: 12 | 13 | Please include **code** that reproduces the issue. 14 | 15 | The [best reproductions](https://stackoverflow.com/help/minimal-reproducible-example) are [self-contained scripts](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) with minimal dependencies. 16 | 17 | ```python 18 | code goes here 19 | ``` 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Fixes # 2 | 3 | Changes proposed in this pull request: 4 | 5 | * 6 | * 7 | * 8 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | # Default GitHub labels 2 | - color: d73a4a 3 | description: "Something isn't working" 4 | name: bug 5 | - color: cfd3d7 6 | description: "This issue or pull request already exists" 7 | name: duplicate 8 | - color: a2eeef 9 | description: "New feature or request" 10 | name: enhancement 11 | - color: 7057ff 12 | description: "Good for newcomers" 13 | name: good first issue 14 | - color: 008672 15 | description: "Extra attention is needed" 16 | name: help wanted 17 | - color: e4e669 18 | description: "This doesn't seem right" 19 | name: invalid 20 | - color: d876e3 21 | description: "Further information is requested" 22 | name: question 23 | - color: ffffff 24 | description: "This will not be worked on" 25 | name: wontfix 26 | 27 | # Keep a Changelog labels 28 | # https://keepachangelog.com/en/1.0.0/ 29 | - color: 0e8a16 30 | description: "For new features" 31 | name: "changelog: Added" 32 | - color: af99e5 33 | description: "For changes in existing functionality" 34 | name: "changelog: Changed" 35 | - color: FFA500 36 | description: "For soon-to-be removed features" 37 | name: "changelog: Deprecated" 38 | - color: 00A800 39 | description: "For any bug fixes" 40 | name: "changelog: Fixed" 41 | - color: ff0000 42 | description: "For now removed features" 43 | name: "changelog: Removed" 44 | - color: 045aa0 45 | description: "In case of vulnerabilities" 46 | name: "changelog: Security" 47 | - color: fbca04 48 | description: "Exclude PR from release draft" 49 | name: "changelog: skip" 50 | 51 | # Other labels 52 | - color: 0366d6 53 | description: "For dependencies" 54 | name: dependencies 55 | - color: e28acf 56 | description: "Documentation" 57 | name: documentation 58 | - color: f4660e 59 | description: "" 60 | name: Hacktoberfest 61 | - color: f4660e 62 | description: "To credit accepted Hacktoberfest PRs" 63 | name: hacktoberfest-accepted 64 | - color: caffaf 65 | description: "Deploy and release" 66 | name: release 67 | - color: fbca04 68 | description: "Unit tests, linting, CI, etc." 69 | name: testing 70 | - color: FFD43B 71 | description: "" 72 | name: Python 2 73 | - color: F25022 74 | description: "" 75 | name: Windows 76 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: "$RESOLVED_VERSION" 2 | tag-template: "$RESOLVED_VERSION" 3 | 4 | categories: 5 | - title: "Added" 6 | labels: 7 | - "changelog: Added" 8 | - "enhancement" 9 | - title: "Changed" 10 | label: "changelog: Changed" 11 | - title: "Deprecated" 12 | label: "changelog: Deprecated" 13 | - title: "Removed" 14 | label: "changelog: Removed" 15 | - title: "Fixed" 16 | labels: 17 | - "changelog: Fixed" 18 | - "bug" 19 | - title: "Security" 20 | label: "changelog: Security" 21 | 22 | exclude-labels: 23 | - "changelog: skip" 24 | 25 | template: | 26 | $CHANGES 27 | 28 | version-resolver: 29 | major: 30 | labels: 31 | - "changelog: Removed" 32 | minor: 33 | labels: 34 | - "changelog: Added" 35 | - "changelog: Changed" 36 | - "changelog: Deprecated" 37 | - "enhancement" 38 | 39 | patch: 40 | labels: 41 | - "changelog: Fixed" 42 | - "bug" 43 | default: minor 44 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ], 6 | "labels": [ 7 | "changelog: skip", 8 | "dependencies" 9 | ], 10 | "packageRules": [ 11 | { 12 | "groupName": "github-actions", 13 | "matchManagers": ["github-actions"], 14 | "separateMajorMinor": "false" 15 | } 16 | ], 17 | "schedule": ["on the first day of the month"] 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/benchmark.yml: -------------------------------------------------------------------------------- 1 | name: Benchmark 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | paths: 9 | - ".github/workflows/benchmark.yml" 10 | - "tests/benchmark.py" 11 | workflow_dispatch: 12 | 13 | jobs: 14 | build: 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | python-version: ["3.11"] 20 | os: [ubuntu-22.04] 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | - run: git fetch --prune --unshallow 25 | 26 | - name: Set up Python ${{ matrix.python-version }} 27 | uses: actions/setup-python@v5 28 | with: 29 | python-version: ${{ matrix.python-version }} 30 | cache: pip 31 | cache-dependency-path: "setup.py" 32 | 33 | - name: Install dependencies 34 | run: | 35 | python -m pip install --upgrade pip 36 | python -m pip install --upgrade orjson simplejson 37 | python -m pip install . 38 | 39 | - name: Tests 40 | shell: bash 41 | run: | 42 | python tests/benchmark.py 43 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Deploy 3 | 4 | on: 5 | push: 6 | branches: 7 | - main 8 | pull_request: 9 | paths: 10 | - ".github/workflows/deploy.yml" 11 | release: 12 | types: 13 | - published 14 | workflow_dispatch: 15 | 16 | env: 17 | FORCE_COLOR: 1 18 | 19 | jobs: 20 | build-native-wheels: 21 | runs-on: ${{ matrix.os }} 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | os: [windows-latest, macOS-latest, ubuntu-latest] 26 | 27 | steps: 28 | - uses: actions/checkout@v4 29 | - run: git fetch --prune --unshallow 30 | 31 | - name: Set up Python 32 | uses: actions/setup-python@v5 33 | with: 34 | python-version: "3.x" 35 | cache: pip 36 | cache-dependency-path: ".github/workflows/deploy.yml" 37 | 38 | # https://github.com/pypa/cibuildwheel 39 | - name: Build wheels 40 | uses: pypa/cibuildwheel@v2.22.0 41 | with: 42 | output-dir: dist 43 | # Options are supplied via environment variables: 44 | env: 45 | # Build separate wheels for macOS's different architectures. 46 | CIBW_ARCHS_MACOS: "x86_64 arm64" 47 | # Build only on Linux architectures that don't need qemu emulation. 48 | CIBW_ARCHS_LINUX: "x86_64 i686" 49 | # Include latest Python beta. 50 | CIBW_ENABLE: cpython-prerelease 51 | # Skip EOL Python versions. 52 | CIBW_SKIP: "pp39*" 53 | # Run the test suite after each build. 54 | CIBW_TEST_REQUIRES: "pytest" 55 | CIBW_TEST_COMMAND: pytest {package}/tests 56 | 57 | - name: Upload as build artifacts 58 | uses: actions/upload-artifact@v4 59 | with: 60 | name: wheels-${{ matrix.os }} 61 | path: dist/*.whl 62 | 63 | build-QEMU-emulated-wheels: 64 | runs-on: ubuntu-latest 65 | strategy: 66 | fail-fast: false 67 | matrix: 68 | python-version: 69 | - pp310 70 | - cp39 71 | - cp310 72 | - cp311 73 | - cp312 74 | - cp313 75 | 76 | steps: 77 | - uses: actions/checkout@v4 78 | - run: git fetch --prune --unshallow 79 | 80 | - name: Set up Python 81 | uses: actions/setup-python@v5 82 | with: 83 | python-version: "3.x" 84 | cache: pip 85 | cache-dependency-path: ".github/workflows/deploy.yml" 86 | 87 | # https://github.com/docker/setup-qemu-action 88 | - name: Set up QEMU 89 | uses: docker/setup-qemu-action@v3 90 | 91 | # https://github.com/pypa/cibuildwheel 92 | - name: Build wheels 93 | uses: pypa/cibuildwheel@v2.22.0 94 | with: 95 | output-dir: dist 96 | # Options are supplied via environment variables: 97 | env: 98 | # Build only the currently selected Linux architecture (so we can 99 | # parallelise for speed). 100 | CIBW_ARCHS_LINUX: "aarch64" 101 | # Likewise, select only one Python version per job to speed this up. 102 | CIBW_BUILD: "${{ matrix.python-version }}-*" 103 | # Include latest Python beta. 104 | CIBW_ENABLE: cpython-prerelease 105 | # Run the test suite after each build. 106 | CIBW_TEST_REQUIRES: "pytest" 107 | CIBW_TEST_COMMAND: pytest {package}/tests 108 | 109 | - name: Upload as build artifacts 110 | uses: actions/upload-artifact@v4 111 | with: 112 | name: wheels-qemu-${{ matrix.python-version }} 113 | path: dist/*.whl 114 | 115 | build-sdist-and-upload: 116 | runs-on: ubuntu-latest 117 | needs: ['build-native-wheels', 'build-QEMU-emulated-wheels'] 118 | permissions: 119 | # IMPORTANT: this permission is mandatory for trusted publishing 120 | id-token: write 121 | 122 | steps: 123 | - uses: actions/checkout@v4 124 | - run: | 125 | git fetch --prune --unshallow 126 | 127 | - name: Set up Python 128 | uses: actions/setup-python@v5 129 | with: 130 | python-version: "3.x" 131 | cache: pip 132 | cache-dependency-path: "setup.py" 133 | 134 | - name: Install dependencies 135 | run: | 136 | python -m pip install -U pip 137 | python -m pip install -U build twine 138 | 139 | - name: Download wheels from build artifacts 140 | uses: actions/download-artifact@v4 141 | with: 142 | pattern: wheels-* 143 | merge-multiple: true 144 | path: dist-wheels/ 145 | 146 | - name: Build package 147 | run: | 148 | git tag 149 | python -m build --sdist 150 | twine check --strict dist/* 151 | twine check --strict dist-wheels/* 152 | 153 | - name: Publish wheels to PyPI 154 | if: github.event.action == 'published' 155 | uses: pypa/gh-action-pypi-publish@release/v1 156 | with: 157 | packages-dir: dist-wheels/ 158 | 159 | - name: Publish sdist to PyPI 160 | if: github.event.action == 'published' 161 | uses: pypa/gh-action-pypi-publish@release/v1 162 | 163 | - name: Publish wheels to TestPyPI 164 | if: | 165 | github.repository == 'ultrajson/ultrajson' && 166 | github.ref == 'refs/heads/main' 167 | uses: pypa/gh-action-pypi-publish@release/v1 168 | with: 169 | repository-url: https://test.pypi.org/legacy/ 170 | packages-dir: dist-wheels/ 171 | 172 | - name: Publish sdist to TestPyPI 173 | if: | 174 | github.repository == 'ultrajson/ultrajson' && 175 | github.ref == 'refs/heads/main' 176 | uses: pypa/gh-action-pypi-publish@release/v1 177 | with: 178 | repository-url: https://test.pypi.org/legacy/ 179 | -------------------------------------------------------------------------------- /.github/workflows/fuzz.yml: -------------------------------------------------------------------------------- 1 | name: Fuzz 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: actions/setup-python@v5 11 | with: 12 | python-version: 3.x 13 | 14 | - name: Install 15 | run: | 16 | python -m pip install -U pip 17 | python -m pip install . 18 | env: 19 | CFLAGS: '-DDEBUG' 20 | 21 | - name: Fuzz 22 | run: python tests/fuzz.py --seed=0:1000 23 | -------------------------------------------------------------------------------- /.github/workflows/labels.yml: -------------------------------------------------------------------------------- 1 | name: Sync labels 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - .github/labels.yml 9 | workflow_dispatch: 10 | 11 | jobs: 12 | sync: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: micnncim/action-label-syncer@v1 17 | with: 18 | prune: false 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: actions/setup-python@v5 12 | with: 13 | python-version: "3.x" 14 | - uses: pre-commit/action@v3.0.1 15 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release drafter 2 | 3 | on: 4 | push: 5 | # branches to consider in the event; optional, defaults to all 6 | branches: 7 | - main 8 | workflow_dispatch: 9 | 10 | jobs: 11 | update_release_draft: 12 | if: github.repository_owner == 'ultrajson' 13 | runs-on: ubuntu-latest 14 | steps: 15 | # Drafts your next release notes as pull requests are merged into "main" 16 | - uses: release-drafter/release-drafter@v6 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/require-pr-label.yml: -------------------------------------------------------------------------------- 1 | name: Require PR label 2 | 3 | on: 4 | pull_request: 5 | types: [opened, reopened, labeled, unlabeled, synchronize] 6 | 7 | jobs: 8 | label: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: mheap/github-action-required-labels@v5 13 | with: 14 | mode: minimum 15 | count: 1 16 | labels: 17 | "changelog: Added, changelog: Changed, changelog: Deprecated, changelog: 18 | Fixed, changelog: Removed, changelog: Security, changelog: skip" 19 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | env: 6 | FORCE_COLOR: 1 7 | 8 | jobs: 9 | test: 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | python-version: ["pypy-3.10", "3.9", "3.10", "3.11", "3.12", "3.13"] 15 | os: [ubuntu-latest] 16 | include: 17 | - { python-version: "pypy-3.10", os: windows-latest } 18 | - { python-version: "pypy-3.10", os: macos-latest } 19 | - { python-version: "3.12", os: windows-latest } 20 | - { python-version: "3.12", os: macos-latest } 21 | - { python-version: "3.13", os: windows-latest } 22 | - { python-version: "3.13", os: macos-latest } 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - name: Set up Python ${{ matrix.python-version }} 28 | uses: actions/setup-python@v5 29 | with: 30 | python-version: ${{ matrix.python-version }} 31 | allow-prereleases: true 32 | cache: pip 33 | cache-dependency-path: "setup.py" 34 | 35 | - name: Install dependencies 36 | run: | 37 | python -m pip install -U pip 38 | python -m pip install -U pytest 39 | python -m pip install . 40 | env: 41 | CFLAGS: '-DDEBUG' 42 | 43 | - name: Tests 44 | run: | 45 | python -m pytest --capture=no 46 | 47 | - name: Test without debug mode 48 | run: | 49 | git clean -Xfd 50 | python -m pip install --force-reinstall . 51 | python -m pytest 52 | 53 | - name: Test with coverage 54 | if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.python-version == '3.10' }} 55 | env: 56 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 57 | run: | 58 | pip install -e . 59 | pip install coverage 60 | CFLAGS="--coverage -O0" python setup.py -q build_ext --inplace -f 61 | coverage run -m pytest 62 | ./scripts/coverage.sh 63 | bash <(curl -s https://codecov.io/bash) -X gcov 64 | 65 | cross-arch: 66 | runs-on: ubuntu-latest 67 | strategy: 68 | fail-fast: false 69 | matrix: 70 | architecture: [ppc64le, s390x, aarch64, arm/v6, 386] 71 | steps: 72 | - uses: actions/checkout@v4 73 | - run: git fetch --prune --unshallow 74 | 75 | # https://github.com/docker/setup-qemu-action 76 | - name: Set up QEMU 77 | uses: docker/setup-qemu-action@v3 78 | 79 | - name: Test 80 | run: | 81 | docker run -v "$PWD:/io" --platform=linux/${{ matrix.architecture }} python:alpine ash -e -c ' 82 | apk add gcc g++ musl-dev git 83 | cd /io 84 | git config --global --add safe.directory /io 85 | pip install . pytest 86 | FORCE_COLOR=1 pytest 87 | ' 88 | 89 | success: 90 | needs: [test, cross-arch] 91 | runs-on: ubuntu-latest 92 | name: test successful 93 | steps: 94 | - name: Success 95 | run: echo Test successful 96 | -------------------------------------------------------------------------------- /.github/zizmor.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | artipacked: 3 | ignore: 4 | - benchmark.yml 5 | - deploy.yml 6 | - fuzz.yml 7 | - labels.yml 8 | - lint.yml 9 | - test.yml 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | *.cover 42 | *.py,cover 43 | .cache 44 | .coverage 45 | .coverage.* 46 | .hypothesis/ 47 | .nox/ 48 | .pytest_cache/ 49 | .testmondata 50 | .tox/ 51 | cover/ 52 | coverage.xml 53 | htmlcov/ 54 | nosetests.xml 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | db.sqlite3-journal 65 | 66 | # Flask stuff: 67 | instance/ 68 | .webassets-cache 69 | 70 | # Scrapy stuff: 71 | .scrapy 72 | 73 | # Sphinx documentation 74 | docs/_build/ 75 | 76 | # PyBuilder 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 99 | __pypackages__/ 100 | 101 | # Celery stuff 102 | celerybeat-schedule 103 | celerybeat.pid 104 | 105 | # SageMath parsed files 106 | *.sage.py 107 | 108 | # Environments 109 | .env 110 | .venv 111 | env/ 112 | venv/ 113 | ENV/ 114 | env.bak/ 115 | venv.bak/ 116 | 117 | # Spyder project settings 118 | .spyderproject 119 | .spyproject 120 | 121 | # Rope project settings 122 | .ropeproject 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | 135 | # pytype static type analyzer 136 | .pytype/ 137 | 138 | # Generated by setuptools_scm 139 | python/version.h 140 | 141 | # Docker wheel build 142 | pip-cache/ 143 | temp-wheels/ 144 | 145 | # gcov coverage files 146 | cov 147 | *.gcov 148 | *.gcda 149 | *.gcno 150 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/asottile/pyupgrade 3 | rev: v3.19.0 4 | hooks: 5 | - id: pyupgrade 6 | args: [--py39-plus] 7 | 8 | - repo: https://github.com/psf/black-pre-commit-mirror 9 | rev: 24.10.0 10 | hooks: 11 | - id: black 12 | args: [--target-version=py39] 13 | 14 | - repo: https://github.com/PyCQA/isort 15 | rev: 5.13.2 16 | hooks: 17 | - id: isort 18 | 19 | - repo: https://github.com/PyCQA/flake8 20 | rev: 7.1.1 21 | hooks: 22 | - id: flake8 23 | additional_dependencies: [flake8-2020, flake8-implicit-str-concat] 24 | 25 | - repo: https://github.com/pre-commit/pygrep-hooks 26 | rev: v1.10.0 27 | hooks: 28 | - id: python-check-blanket-noqa 29 | - id: rst-backticks 30 | 31 | - repo: https://github.com/pre-commit/pre-commit-hooks 32 | rev: v5.0.0 33 | hooks: 34 | - id: check-json 35 | - id: check-merge-conflict 36 | - id: check-toml 37 | - id: check-yaml 38 | - id: end-of-file-fixer 39 | - id: trailing-whitespace 40 | exclude: "^.github/.*_TEMPLATE.md" 41 | 42 | - repo: https://github.com/woodruffw/zizmor-pre-commit 43 | rev: v0.9.1 44 | hooks: 45 | - id: zizmor 46 | 47 | - repo: https://github.com/asottile/setup-cfg-fmt 48 | rev: v2.7.0 49 | hooks: 50 | - id: setup-cfg-fmt 51 | args: [--include-version-classifiers, --max-py-version=3.13] 52 | ci: 53 | autoupdate_schedule: quarterly 54 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Developed by ESN, an Electronic Arts Inc. studio. 2 | Copyright (c) 2014, Electronic Arts Inc. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of ESN, Electronic Arts Inc. nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | ---- 28 | 29 | Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) 30 | https://github.com/client9/stringencoders 31 | 32 | Copyright 2005, 2006, 2007 33 | Nick Galbreath -- nickg [at] modp [dot] com 34 | All rights reserved. 35 | 36 | Redistribution and use in source and binary forms, with or without 37 | modification, are permitted provided that the following conditions are 38 | met: 39 | 40 | Redistributions of source code must retain the above copyright 41 | notice, this list of conditions and the following disclaimer. 42 | 43 | Redistributions in binary form must reproduce the above copyright 44 | notice, this list of conditions and the following disclaimer in the 45 | documentation and/or other materials provided with the distribution. 46 | 47 | Neither the name of the modp.com nor the names of its 48 | contributors may be used to endorse or promote products derived from 49 | this software without specific prior written permission. 50 | 51 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 52 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 53 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 54 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 55 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 56 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 57 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 61 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 | 63 | This is the standard "new" BSD license: 64 | http://www.opensource.org/licenses/bsd-license.php 65 | 66 | https://github.com/client9/stringencoders/blob/cfd5c1507325ae497ea9bacdacba12c0ffd79d30/COPYING 67 | 68 | ---- 69 | 70 | Numeric decoder derived from from TCL library 71 | https://opensource.apple.com/source/tcl/tcl-14/tcl/license.terms 72 | * Copyright (c) 1988-1993 The Regents of the University of California. 73 | * Copyright (c) 1994 Sun Microsystems, Inc. 74 | 75 | This software is copyrighted by the Regents of the University of 76 | California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState 77 | Corporation and other parties. The following terms apply to all files 78 | associated with the software unless explicitly disclaimed in 79 | individual files. 80 | 81 | The authors hereby grant permission to use, copy, modify, distribute, 82 | and license this software and its documentation for any purpose, provided 83 | that existing copyright notices are retained in all copies and that this 84 | notice is included verbatim in any distributions. No written agreement, 85 | license, or royalty fee is required for any of the authorized uses. 86 | Modifications to this software may be copyrighted by their authors 87 | and need not follow the licensing terms described here, provided that 88 | the new terms are clearly indicated on the first page of each file where 89 | they apply. 90 | 91 | IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY 92 | FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 93 | ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY 94 | DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE 95 | POSSIBILITY OF SUCH DAMAGE. 96 | 97 | THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, 98 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 99 | FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE 100 | IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE 101 | NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 102 | MODIFICATIONS. 103 | 104 | GOVERNMENT USE: If you are acquiring this software on behalf of the 105 | U.S. government, the Government shall have only "Restricted Rights" 106 | in the software and related documentation as defined in the Federal 107 | Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you 108 | are acquiring the software on behalf of the Department of Defense, the 109 | software shall be classified as "Commercial Computer Software" and the 110 | Government shall have only "Restricted Rights" as defined in Clause 111 | 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the 112 | authors grant the U.S. Government and others acting in its behalf 113 | permission to use and distribute the software in accordance with the 114 | terms specified in this license. 115 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include python/version.h 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UltraJSON 2 | 3 | [![PyPI version](https://img.shields.io/pypi/v/ujson.svg?logo=pypi&logoColor=FFE873)](https://pypi.org/project/ujson) 4 | [![Supported Python versions](https://img.shields.io/pypi/pyversions/ujson.svg?logo=python&logoColor=FFE873)](https://pypi.org/project/ujson) 5 | [![PyPI downloads](https://img.shields.io/pypi/dm/ujson.svg)](https://pypistats.org/packages/ujson) 6 | [![GitHub Actions status](https://github.com/ultrajson/ultrajson/workflows/Test/badge.svg)](https://github.com/ultrajson/ultrajson/actions) 7 | [![codecov](https://codecov.io/gh/ultrajson/ultrajson/branch/main/graph/badge.svg)](https://codecov.io/gh/ultrajson/ultrajson) 8 | [![DOI](https://zenodo.org/badge/1418941.svg)](https://zenodo.org/badge/latestdoi/1418941) 9 | [![Code style: Black](https://img.shields.io/badge/code%20style-Black-000000.svg)](https://github.com/psf/black) 10 | 11 | UltraJSON is an ultra fast JSON encoder and decoder written in pure C with bindings for 12 | Python 3.9+. 13 | 14 | Install with pip: 15 | 16 | ```sh 17 | python -m pip install ujson 18 | ``` 19 | 20 | ## Project status 21 | 22 | > [!WARNING] 23 | > UltraJSON's architecture is fundamentally ill-suited to making changes without 24 | > risk of introducing new security vulnerabilities. As a result, this library 25 | > has been put into a *maintenance-only* mode. Support for new Python versions 26 | > will be added and critical bugs and security issues will still be 27 | > fixed but all other changes will be rejected. Users are encouraged to migrate 28 | > to [orjson](https://pypi.org/project/orjson/) which is both much faster and 29 | > less likely to introduce a surprise buffer overflow vulnerability in the 30 | > future. 31 | 32 | ## Usage 33 | 34 | May be used as a drop in replacement for most other JSON parsers for Python: 35 | 36 | ```pycon 37 | >>> import ujson 38 | >>> ujson.dumps([{"key": "value"}, 81, True]) 39 | '[{"key":"value"},81,true]' 40 | >>> ujson.loads("""[{"key": "value"}, 81, true]""") 41 | [{'key': 'value'}, 81, True] 42 | ``` 43 | 44 | ### Encoder options 45 | 46 | #### encode_html_chars 47 | 48 | Used to enable special encoding of "unsafe" HTML characters into safer Unicode 49 | sequences. Default is `False`: 50 | 51 | ```pycon 52 | >>> ujson.dumps("