Agree it feels unnatural, but you can hide it from the remote client with a thin encoding step right before sending, so producers keep working with normal nested JSON.
A small helper that encodes only the VARIANT columns:
import json
VARIANT_COLUMNS = {"ValueJson"}
def to_zerobus_record(record: dict) -> dict:
return {
k: json.dumps(v) if k in VARIANT_COLUMNS and not isinstance(v, str) else v
for k, v in record.items()
}
record = {"a": "E", "b": 123, "c": "xyz", "ValueJson": {"x": "y"}}
payload = [to_zerobus_record(record)]
# -> [{"a": "E", "b": 123, "c": "xyz", "ValueJson": "{\"x\": \"y\"}"}]
On the Databricks side nothing changes: it lands as a real VARIANT, not a string, so you query it normally:
SELECT
a,
ValueJson:x::string AS x,
variant_get(ValueJson, '$.x', 'string') AS x_alt
FROM catalog.schema.your_table;
If several producers send data, ship this helper in a small shared client package so nobody needs to know about the rule.