Skip to main content
Google’s APIs describe several fields as protobuf well-known types. These mirror them as Pydantic models, so a schema can be strict about a dynamically typed cell while the proto_json transform writes the plain JSON the wire actually wants. Needed by anything Sheets-shaped: values in a Sheets update is List[List[Value]], and a partial update carries a FieldMask.

Value

A dynamically typed value: null, number, string, bool, a nested Struct, or a ListValue. Exactly one variant must be set — zero or two raise a ValidationError from check_one_variant.
Optional[Literal['NULL_VALUE']]
A null.
Optional[float]
A double.
Optional[str]
A string.
Optional[bool]
A boolean.
Optional[Struct]
A structured value.
Optional[ListValue]
A repeated value.
The coerce_primitive validator accepts a plain JSON primitive and promotes it to the right variant, so a model can write "hello" where the type says Value:
Booleans are checked before numbers, so True is a bool_value rather than 1.0.

ListValue

A wrapper around a repeated field of values. Its JSON representation is an array.
List[Value]
required
The elements.

Struct

Structured data: a map of names to dynamically typed values. Its JSON representation is an object.
Optional[Dict[str, Value]]
Unordered map of dynamically typed values.

FieldMask

A set of symbolic field paths, naming what a partial update should touch.
List[str]
required
Dot-separated camelCase field paths, e.g. "userEnteredValue" or "userEnteredFormat.horizontalAlignment".
The coerce_shorthand validator also accepts the two shapes a model is likely to produce — a list, or the comma-separated wire string:

NullValue

The single-member enum protobuf uses for null. It is the type of Value.null_value; write it directly only when declaring a field that is always null.

Wire encoding

Protobuf’s JSON mapping is not the struct representation. Value encodes as the bare primitive, ListValue as an array, Struct as an object, FieldMask as one comma-separated string. Format("proto_json") performs the first three and Format("field_mask") the fourth: