Skip to content

shape_decoder

Function: warmhub.shape_decoder

shape_decoder(cls: type[T])

Build a decoder for a dataclass whose fields are the data keys.

This is what decode_as= calls. Use it directly only to build a decoder once and reuse it across many reads:

reading = shape_decoder(Reading)
page = repo.things.head(shape="Reading", decoder=reading)

What it does:

  • Reads each field by its exact name. No camelCase conversion, ever.
  • A missing key with a field default uses the default; without one it raises PayloadDecodeError naming the field and the shape.
  • Checks the value actually received against the field’s annotation: the four JSON scalars, optionals of them, and homogeneous arrays and string-keyed objects of them. int where float is declared is accepted and widened, because JSON has a single number type.
  • Ignores keys the dataclass does not declare. A repo shape that gains a field must not break a deployed reader.

Raises TypeError: immediately, at the call rather than at read time, if cls is not a dataclass, if its annotations do not resolve, or if a field is annotated with something this adapter cannot check. The last one is the point: a decoder that silently validates nothing is worse than one that refuses, because only the refusal is visible.