Skip to content

fix(queue): serialize maps as objects for json content type - #1093

Open
PedroRosalba wants to merge 1 commit into
cloudflare:mainfrom
PedroRosalba:fix/queue-json-maps
Open

PedroRosalba wants to merge 1 commit into
cloudflare:mainfrom
PedroRosalba:fix/queue-json-maps

Conversation

@PedroRosalba

Copy link
Copy Markdown

Problem

Queue::send / send_batch serialize the message with serde_wasm_bindgen::to_value, whose default serializer writes Rust maps (HashMap, BTreeMap, serde_json::Value::Object) as a JS Map and byte buffers as a Uint8Array. The default content type is json, and the runtime JSON-encodes the body before storing it, so a Map arrives as {} and a Uint8Array as an object keyed by index. Consumers silently lose every map-typed field, and no consumer-side change can recover them because the data is already gone on the wire.

This is the producer-side half of #1013: the reporter's payload holds serde_json::Value objects, which are exactly the values that get flattened to {}. #1048 (body_json, content_type) addresses the consumer side and is complementary to this change; both are needed for that issue.

Fix

When the content type is json, serialize with serialize_maps_as_objects(true) and serialize_bytes_as_arrays(true). The v8 and text paths are unchanged. json_compatible() was deliberately not used because serialize_missing_as_null would change the wire format of every Option::None field.

Observable changes (json path only): map fields now arrive with their data instead of {}; serde_bytes fields arrive as arrays instead of index-keyed objects; a map with non-string keys now returns an error at send time instead of silently sending {}.

Tests

Adds a MapQueueBody message with a HashMap and a serde_json::Value field, routes for send and send_batch, and a consumer branch that records what arrived. The new specs fail on main (2 failures) and pass with this change; full suite 147 passed / 4 skipped.

Tested on macOS (Apple Silicon) only.

Refs #1013

Queue::send and send_batch serialize the message with
serde_wasm_bindgen::to_value, which writes Rust maps (HashMap, BTreeMap,
serde_json::Value::Object) as JS Map and byte buffers as Uint8Array. The
default content type is json, and the runtime JSON-encodes the body, so a
Map arrives as {} and a Uint8Array as an object keyed by index: consumers
silently lose every map-typed field.

Serialize the body with serialize_maps_as_objects and
serialize_bytes_as_arrays when the content type is json; v8 and text sends
are unchanged. Add a test that sends a struct with a HashMap and a
serde_json::Value field through send and send_batch and asserts the
round-trip.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant