Aggregation EJSON round-tripping and BSON type preservation
Parent: MongoDB Aggregation Pipeline · Published reference · snapshot 2026-10-29
↓ Facts as markdownall context files
Source-anchored research for Aggregation EJSON round-tripping and BSON type preservation. Run status: COMPLETED.
These notes link each claim to its source. Some citations identify archived research reports that are no longer hosted on this site. A published reference means the content is available; it does not certify independent review or accuracy.Read the editorial policy and follow the sources before relying on a claim.
How it works
- Choose client options explicitly when preserving types across an aggregation export. Aggregation $serializeEJSON defaults to canonical, whereas mongosh EJSON.serialize and JavaScript EJSON.parse default to relaxed behavior; the JavaScript parser accepts relaxed:false to retain BSON type objects. (medium confidence) [source]
- The aggregation serializer defaults relaxed to false. Canonical EJSON distinguishes Int32, Int64 and Double with $numberInt, $numberLong and $numberDouble wrappers whose payloads are strings; use this form when preserving numeric BSON types matters. (medium confidence) [source]
- Do not transfer the shell serializer default to the aggregation operator: mongosh EJSON.serialize() documents relaxed:true by default, whereas aggregation $serializeEJSON documents relaxed:false by default. Select the mode explicitly when moving serialization logic between these APIs. (medium confidence) [source]
Problems, failure modes and limitations
- Both aggregation operators document null or missing input as returning null. Each accepts onError; without it a conversion error stops the operation. Consequently, these operators do not retain the distinction between missing and explicit null input at their result boundary. (medium confidence) [source]
- Relaxed EJSON cannot guarantee numeric type fidelity. Its parser rules allow integer values to become the smallest exact BSON integer type, and permit a Double with precision loss when an integer cannot be represented exactly. (medium confidence) [source]
- Canonical EJSON type preservation does not guarantee an exact round trip for every BSON document. The specification warns that BSON documents have ordered fields while JSON objects are unordered, and EJSON cannot escape arbitrary $-prefixed keys that collide with recognized type wrappers. DRIVERS-3456 illustrates a literal nested $date string becoming a BSON Date after a client EJSON round trip; this is format/client evidence, not a reproduced aggregation-server defect. (medium confidence) [source]
Comparisons and alternatives
- $serializeEJSON returns a BSON value/document containing EJSON type wrappers, rather than directly returning JSON text. Its documented string export pattern applies $toString to that result. Conversely, $deserializeEJSON expects parsed EJSON wrapper data; the documented string import pattern parses JSON into an object before deserialization. (medium confidence) [source]
- For a downstream EJSON consumer, Debezium documents json.serialization.mode=extended as selecting EJSON v2 canonical representation for MongoDB document fields. Its legacy default mixes EJSON v1 strict full-document fields with EJSON v2 relaxed updatedFields. Check the consumer mode rather than assuming every EJSON-labelled payload preserves numeric types identically. This is connector behavior, not an aggregation operator default. (low confidence) (verified as of 2026-10-27) [source]
- Relaxed EJSON retains non-finite Double values through $numberDouble wrappers, and dates outside years 1970 through 9999 use the canonical milliseconds wrapper even in relaxed mode. Test these boundaries rather than assuming all relaxed doubles are native JSON numbers or all relaxed dates are ISO strings. (low confidence) [source]
Facts and statements
- MongoDB documents $serializeEJSON and $deserializeEJSON as aggregation expressions introduced in version 8.3, for converting between BSON values and Extended JSON representations. (medium confidence) (verified as of 2026-10-14) [source]
- $serializeEJSON returns a BSON document containing EJSON wrappers. Its relaxed option defaults to false, selecting canonical format; relaxed:true represents Int32, Int64 and finite Double values as native JSON numbers. (medium confidence) [source]
- Canonical wrappers distinguish Int32 ($numberInt), Int64 ($numberLong) and Double ($numberDouble). The documented inverse also restores ObjectId, Date, Binary with subtype, and regular-expression wrappers to their corresponding BSON types. (medium confidence) [source]
- As a verification method, compare restored BSON types as well as values, especially equal-valued Int32, Int64 and Double fields. This recommendation follows from canonical numeric wrappers and the relaxed parser rules; visual equality of JSON numbers does not establish type fidelity. (medium confidence) [source]
- NoSQLBooster 11.1 announces helper methods for both aggregation EJSON operators, including $.serializeEJSON and $.deserializeEJSON. This is first-party evidence of client helper support, not an independent test of server round-trip correctness. (low confidence) (verified as of 2026-09-30) [source]
- Percona lists both EJSON expressions among the additions in its July 30, 2026 announcement of Percona Server for MongoDB 8.3 Technical Preview. That announcement does not provide round-trip edge-case tests. (low confidence) (verified as of 2026-07-30) [source]
- Relaxed EJSON trades numeric type preservation for readability: Int32 and Int64 become ordinary JSON integers, and finite doubles become JSON numbers. Generic parsers can erase the original numeric width and can lose precision for large integers; relaxed output is therefore unsuitable for guaranteeing the original numeric BSON types across a JSON text round trip. (medium confidence) [source]
- Canonical type encoding also carries ObjectId hex bytes, Binary base64 plus subtype, and Date epoch milliseconds via $date/$numberLong. Relaxed output still uses wrappers for ObjectId, Binary and Decimal128; relaxed does not mean wrapper-free JSON. (medium confidence) [source]
- NoSQLBooster 11.1 documents query-builder helpers $.serializeEJSON("$document") and $.deserializeEJSON("$ejsonString"). This establishes tooling support for the named conversions, but its description of the latter as accepting an EJSON string should not override the server operator documentation requiring parsed wrapper input. (medium confidence) (verified as of 2026-09-30) [source]
Children
- Canonical versus relaxed EJSON numeric fidelity (frontier)
- Reserved type-wrapper key collisions (frontier)
- BSON-aware round-trip verification (frontier)
- Canonical versus relaxed EJSON numeric type preservation (frontier)
- EJSON wrapper collisions with literal dollar-prefixed fields (frontier)
- Client and server EJSON defaults (frontier)
- EJSON round-trip validation with BSON type assertions (frontier)
Frontier under this node: BSON-aware round-trip verification, Canonical versus relaxed EJSON numeric fidelity, Canonical versus relaxed EJSON numeric type preservation, Client and server EJSON defaults, EJSON round-trip validation with BSON type assertions, EJSON wrapper collisions with literal dollar-prefixed fields, Reserved type-wrapper key collisions