ProvenPin Install

orjson and msgspec encode/decode parity helpers: working versions (tested 2026-10-16)

Run orjson and msgspec side by side with canonical sort-key and non-str-key options, a shared Struct hook and typed decoding, and pin down where their bytes diverge.

passed6 passed · 0 failed2026-10-16 00:01 UTC
Status
passed
Last passed
2026-10-16 00:01 UTC
Tests
6 / 6
Language
Python
Runtime
Python 3.13.16
pinned versions3
orjson@3.13.0msgspec@0.22.0pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38826982604

The code

Exactly the files that passed. Your agent can pull them with get_recipe("orjson-msgspec-encode-parity") (install), or see them on GitHub.

requirements.txt
orjson==3.13.0
msgspec==0.22.0
pytest==9.1.1
parity.py
from __future__ import annotations

from typing import Any

import msgspec
import orjson


def _hook(obj: Any) -> Any:
    if isinstance(obj, msgspec.Struct):
        return msgspec.to_builtins(obj)
    raise TypeError(f"orjson cannot encode {type(obj).__name__}")


def orjson_bytes(obj: Any, *, sort_keys: bool = False) -> bytes:
    option = orjson.OPT_NON_STR_KEYS | (orjson.OPT_SORT_KEYS if sort_keys else 0)
    return orjson.dumps(obj, default=_hook, option=option)


def msgspec_bytes(obj: Any, *, sort_keys: bool = False) -> bytes:
    return msgspec.json.encode(obj, order="sorted" if sort_keys else None)


def encode_both(obj: Any) -> tuple[bytes, bytes]:
    return orjson_bytes(obj, sort_keys=True), msgspec_bytes(obj, sort_keys=True)


def assert_parity(obj: Any) -> None:
    o, m = encode_both(obj)
    if o != m:
        raise AssertionError(f"orjson={o!r} msgspec={m!r}")


def decode_as(payload: bytes, type_: Any) -> Any:
    return msgspec.json.decode(payload, type=type_)
tests/test_parity.py
import datetime as dt

import msgspec
import orjson
import pytest
from parity import (
    assert_parity,
    decode_as,
    msgspec_bytes,
    orjson_bytes,
)


def test_sorted_scalars_have_byte_parity():
    payload = {"b": 1, "a": [1, 2.5, "x", True, None]}
    o, m = orjson_bytes(payload, sort_keys=True), msgspec_bytes(payload, sort_keys=True)
    assert o == m == b'{"a":[1,2.5,"x",true,null],"b":1}'
    assert_parity(payload)


def test_utc_datetime_suffix_is_not_parity():
    when = dt.datetime(2024, 1, 2, 3, 4, 5, tzinfo=dt.timezone.utc)
    assert orjson_bytes(when, sort_keys=True) == b'"2024-01-02T03:04:05+00:00"'
    assert msgspec_bytes(when, sort_keys=True) == b'"2024-01-02T03:04:05Z"'
    with pytest.raises(AssertionError):
        assert_parity({"at": when})


def test_int_keys_need_non_str_option():
    with pytest.raises(TypeError):
        orjson.dumps({1: "a"})
    assert orjson_bytes({1: "a"}) == b'{"1":"a"}'
    assert orjson_bytes({1: "a", 2: "b"}) == msgspec_bytes({1: "a", 2: "b"})
    with pytest.raises(TypeError):
        msgspec.json.encode({1: "a"}, order="sorted")


def test_non_finite_floats_collapse_to_null():
    assert_parity({"nan": float("nan"), "inf": float("inf")})
    assert msgspec.json.decode(msgspec_bytes({"x": float("nan")})) == {"x": None}


class User(msgspec.Struct):
    name: str
    age: int


def test_struct_encodes_via_hook_and_decodes_typed():
    user = User("ada", 36)
    assert orjson_bytes(user, sort_keys=True) == b'{"age":36,"name":"ada"}'
    assert_parity(user)
    assert decode_as(msgspec_bytes(user), User) == user
    assert orjson.loads(orjson_bytes(user)) == {"name": "ada", "age": 36}


def test_decode_errors_share_value_error_base():
    for decode in (orjson.loads, msgspec.json.decode):
        with pytest.raises(ValueError):
            decode(b"{bad")
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.