GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • msgspec

This view

  • Original page
  • New address

GeezerVison is showing msgspec.dev — Usage

Usage¶

msgspec supports multiple serialization protocols, accessed through separate submodules:

  • msgspec.json (JSON)

  • msgspec.msgpack (MessagePack)

  • msgspec.yaml (YAML)

  • msgspec.toml (TOML)

Each supports a consistent interface, making it simple to switch between protocols as needed.

Encoding¶

Each submodule has an encode method for encoding Python objects using the respective protocol.

>>> import msgspec

>>> # Encode as JSON
... msgspec.json.encode({"hello": "world"})
b'{"hello":"world"}'

>>> # Encode as msgpack
... msgspec.msgpack.encode({"hello": "world"})
b'\x81\xa5hello\xa5world'

Note that if you’re making multiple calls to encode, it’s more efficient to create an Encoder once and use the Encoder.encode method instead.

>>> import msgspec

>>> # Create a JSON encoder
... encoder = msgspec.json.Encoder()

>>> # Encode as JSON using the encoder
... encoder.encode({"hello": "world"})
b'{"hello":"world"}'

Decoding¶

Each submodule has decode method for decoding messages using the respective protocol.

>>> import msgspec

>>> # Decode JSON
... msgspec.json.decode(b'{"hello":"world"}')
{'hello': 'world'}

>>> # Decode msgpack
... msgspec.msgpack.decode(b'\x81\xa5hello\xa5world')
{'hello': 'world'}

Note that if you’re making multiple calls to decode, it’s more efficient to create a Decoder once and use the Decoder.decode method instead.

>>> import msgspec

>>> # Create a JSON decoder
... decoder = msgspec.json.Decoder()

>>> # Decode JSON using the decoder
... decoder.decode(b'{"hello":"world"}')
{'hello': 'world'}

Typed Decoding¶

msgspec optionally supports specifying the expected output types during decoding. This serves a few purposes:

  • Often serialized data has a fixed schema (e.g. a request handler in a REST api expects a certain JSON structure). Specifying the expected types allows msgspec to perform validation during decoding, with no added runtime cost.

  • Python has a much richer type system than serialization protocols like JSON or MessagePack. Specifying the output types lets msgspec decode messages into types other than the defaults described above (e.g. decoding JSON objects into a Struct instead of the default dict).

  • The type annotations used to describe the expected types are compatible with tools like mypy or pyright, providing excellent editor integration.

msgspec uses Python type annotations to describe the expected types. A wide variety of builtin types are supported.

Here we define a user schema as a Struct type. We then pass the type to decode via the type keyword argument:

>>> import msgspec

>>> class User(msgspec.Struct):
...     name: str
...     groups: set[str] = set()
...     email: str | None = None

>>> msgspec.json.decode(
...     b'{"name": "alice", "groups": ["admin", "engineering"]}',
...     type=User
... )
User(name='alice', groups={'admin', 'engineering'}, email=None)

If a message doesn’t match the expected type, an error is raised.

>>> msgspec.json.decode(
...     b'{"name": "bill", "groups": ["devops", 123]}',
...     type=User
... )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
msgspec.ValidationError: Expected `str`, got `int` - at `$.groups[1]`

“Strict” vs “Lax” Mode¶

Unlike some other libraries (e.g. pydantic), msgspec won’t perform any unsafe implicit conversion by default (“strict” mode). For example, if an integer is specified and a string is provided instead, an error is raised rather than attempting to cast the string to an int.

>>> msgspec.json.decode(b'[1, 2, "3"]', type=list[int])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
msgspec.ValidationError: Expected `int`, got `str` - at `$[2]`

For cases where you’d like a more lax set of conversion rules, you can pass strict=False to any decode function or Decoder class (“lax” mode). See Supported Types for information on how this affects individual types.

>>> msgspec.json.decode(b'[1, 2, "3"]', type=list[int], strict=False)
[1, 2, 3]

Converting to and from Builtin Types¶

In some cases, msgspec only needs to process part of a message, and the rest is handled by another library. For these situations, msgspec.to_builtins and msgspec.convert convert between high-level types and plain builtin types (dict, list, str, int, …) without going through an encoded representation.

  • msgspec.to_builtins is the “encoding” half. It applies the same semantics as msgspec.json.encode / msgspec.msgpack.encode - just with builtin Python types as the output rather than an encoded byte string. This includes:

    • Struct-level settings: rename, Omitting Default Values, array_like, and tag for tagged unions.

    • Omission of UNSET fields.

    • Recursive expansion of nested msgspec.Struct, dataclasses.dataclass, attrs, typing.TypedDict, and typing.NamedTuple values.

    • Value-level conversions of types that don’t map directly to builtin types: bytes / bytearray / memoryview to base64 string, datetime.datetime / datetime.date / datetime.time / datetime.timedelta to ISO 8601 string, uuid.UUID and decimal.Decimal to string, set / frozenset to list, frozendict to dict, enum.Enum to its member value.

    • Optional enc_hook, str_keys, order, and builtin_types kwargs for tuning the output to the wrapping protocol.

  • msgspec.convert is the “decoding” half: it takes builtin types and validates them against a schema, producing high-level types.

>>> import msgspec

>>> class User(msgspec.Struct, omit_defaults=True):
...     name: str
...     groups: set[str] = set()
...     email: str | None = None

>>> alice = User("alice")

>>> # to_builtins applies omit_defaults and expands nested types
... msgspec.to_builtins(alice)
{'name': 'alice'}

>>> # convert is the inverse operation
... msgspec.convert({"name": "bill", "groups": ["devops"]}, User)
User(name='bill', groups={'devops'}, email=None)

See Converters for a more detailed guide, including how to use these functions to add msgspec support for additional serialization protocols.

Note that msgspec.structs.asdict and msgspec.structs.astuple are not equivalent to msgspec.to_builtins. They are modeled on dataclasses.asdict / dataclasses.astuple: a one-to-one conversion of a single struct instance to a dict or tuple, using the raw attribute names.

None of the semantics listed above apply. Every field is included regardless of omit_defaults or msgspec.UNSET, rename and tag are ignored, nested msgspec.Struct / dataclasses.dataclass / attrs values are left as-is, and value-level types (bytes, datetime.datetime, uuid.UUID, decimal.Decimal, enum.Enum, …) are not converted.

Prefer msgspec.to_builtins when the output is intended for serialization.

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.