Signed-off-by: luofucong <luofc@foxmail.com>
This commit is contained in:
luofucong
2026-07-03 20:02:32 +08:00
parent 82ca54bd9a
commit 112e89da38

View File

@@ -160,6 +160,16 @@ impl JsonVariant {
}
}
fn contains_empty_object(&self) -> bool {
match self {
JsonVariant::Array(array) => array.iter().any(JsonVariant::contains_empty_object),
JsonVariant::Object(object) => {
object.is_empty() || object.values().any(JsonVariant::contains_empty_object)
}
_ => false,
}
}
fn as_ref(&self) -> JsonVariantRef<'_> {
match self {
JsonVariant::Null => JsonVariantRef::Null,
@@ -433,7 +443,7 @@ impl JsonValue {
/// 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: &JsonNativeType) -> Result<()> {
if is_include(expected, self.json_type()) {
if is_include(expected, self.json_type()) && !self.json_variant.contains_empty_object() {
return Ok(());
}
@@ -896,6 +906,23 @@ mod tests {
])))
);
// Empty objects have native type Null, but the value still needs alignment
// before converting into a typed struct value.
let expected = JsonNativeType::Object(JsonObjectType::from([(
"empty".to_string(),
JsonNativeType::Null,
)]));
let mut value = parse_json_value(r#"{"empty":{}}"#);
assert_eq!(value.json_type(), &expected);
value.try_align(&expected)?;
assert_eq!(
value,
JsonValue::from(JsonVariant::Object(BTreeMap::from([(
"empty".to_string(),
JsonVariant::Null,
)])))
);
// Object alignment should fail if the expected type misses any field from the value.
let expected = JsonNativeType::Object(JsonObjectType::from([(
"items".to_string(),