diff --git a/src/datatypes/src/json/value.rs b/src/datatypes/src/json/value.rs index 575271ae7e..e2422ca78d 100644 --- a/src/datatypes/src/json/value.rs +++ b/src/datatypes/src/json/value.rs @@ -419,6 +419,19 @@ impl JsonValue { helper(self.json_variant) } + /// Recursively aligns this JSON value to `expected` in place. This is to make JSON values fill + /// into a [StructArray], which requires a unified static datatype. + /// + /// Alignment follows these rules: + /// - `Null` aligns to any type, and any value aligns to `Null` as `Null`. + /// - Numbers are converted only within compatible number categories. + /// - Arrays align each element recursively to the expected item type. + /// - Objects require `expected` to contain all fields from the current value. Missing expected + /// fields are filled with `Null`. + /// - `Variant` preserves the original JSON payload as serialized bytes. + /// + /// Returns an error if the value cannot be aligned without losing existing object fields or + /// when a scalar type conversion is incompatible. pub(crate) fn try_align(&mut self, expected: &JsonType) -> Result<()> { if self.json_type() == expected { return Ok(()); diff --git a/src/datatypes/src/types/json_type.rs b/src/datatypes/src/types/json_type.rs index f8629b7f17..d296dc4fcb 100644 --- a/src/datatypes/src/types/json_type.rs +++ b/src/datatypes/src/types/json_type.rs @@ -225,6 +225,10 @@ impl JsonType { /// Try to merge this json type with others, error on datatype conflict. pub fn merge(&mut self, other: &JsonType) -> Result<()> { + if self == other { + return Ok(()); + } + match (&self.format, &other.format) { (JsonFormat::Jsonb, JsonFormat::Jsonb) => Ok(()), (JsonFormat::Json2(this), JsonFormat::Json2(that)) => {