Fix JMAP Patching nested objects with values fails

This commit is contained in:
Maurus Decimus
2026-05-05 19:04:43 +02:00
parent 175f34ea85
commit fc3ea2b31a
7 changed files with 264 additions and 43 deletions

View File

@@ -310,26 +310,24 @@ impl<K: MapItem, V: RegistryJsonPatch> RegistryJsonPatch for VecMap<K, V> {
value: JmapValue<'x>,
) -> PatchResult<'x> {
match (pointer.next(), value) {
(Some(JsonPointerItem::Number(idx)), Value::Null) => {
(Some(JsonPointerItem::Number(idx)), value) => {
if let Some(key) = K::try_from_integer(*idx) {
self.remove(&key);
return Ok(MaybeUnpatched::Patched);
}
}
(Some(JsonPointerItem::Key(key)), Value::Null) => {
if let Some(key) = K::try_from_string(key.to_string().as_ref()) {
self.remove(&key);
return Ok(MaybeUnpatched::Patched);
return if matches!(value, Value::Null) && !pointer.has_next() {
self.remove(&key);
Ok(MaybeUnpatched::Patched)
} else {
self.get_mut_or_insert(key).patch(pointer, value)
};
}
}
(Some(JsonPointerItem::Key(key)), value) => {
if let Some(key) = K::try_from_string(key.to_string().as_ref()) {
return self.get_mut_or_insert(key).patch(pointer, value);
}
}
(Some(JsonPointerItem::Number(idx)), value) => {
if let Some(key) = K::try_from_integer(*idx) {
return self.get_mut_or_insert(key).patch(pointer, value);
return if matches!(value, Value::Null) && !pointer.has_next() {
self.remove(&key);
Ok(MaybeUnpatched::Patched)
} else {
self.get_mut_or_insert(key).patch(pointer, value)
};
}
}
(None, Value::Object(items)) => {

View File

@@ -95,34 +95,31 @@ impl<T: RegistryJsonPatch + Default + Debug> RegistryJsonPatch for List<T> {
value: JmapValue<'x>,
) -> PatchResult<'x> {
match (pointer.next(), value) {
(Some(JsonPointerItem::Number(key)), Value::Null)
if self.0.remove(&(*key as u32)).is_some() =>
{
return Ok(MaybeUnpatched::Patched);
}
(Some(JsonPointerItem::Key(key)), Value::Null) => {
if let Ok(key) = key.to_string().parse::<u32>()
&& self.0.remove(&key).is_some()
{
return Ok(MaybeUnpatched::Patched);
(Some(JsonPointerItem::Number(key)), value) => {
let key = *key as u32;
if matches!(value, Value::Null) && !pointer.has_next() {
if self.0.remove(&key).is_some() {
return Ok(MaybeUnpatched::Patched);
}
} else {
let result = self.0.get_mut_or_insert(key).patch(pointer, value);
self.0.sort_unstable_by_key();
return result;
}
}
(Some(JsonPointerItem::Key(key)), value) => {
if let Ok(key) = key.to_string().parse::<u32>() {
let result = self.0.get_mut_or_insert(key).patch(pointer, value);
self.0.sort_unstable_by_key();
return result;
if matches!(value, Value::Null) && !pointer.has_next() {
if self.0.remove(&key).is_some() {
return Ok(MaybeUnpatched::Patched);
}
} else {
let result = self.0.get_mut_or_insert(key).patch(pointer, value);
self.0.sort_unstable_by_key();
return result;
}
}
}
(Some(JsonPointerItem::Number(key)), value) => {
let result = self.0.get_mut_or_insert(*key as u32).patch(pointer, value);
self.0.sort_unstable_by_key();
return result;
}
(None, Value::Object(items)) => {
self.0.clear();
for (key, value) in items.into_vec() {

View File

@@ -140,19 +140,31 @@ impl<T: MapItem + Default> RegistryJsonPatch for Map<T> {
) -> PatchResult<'x> {
match (pointer.next(), value) {
(Some(JsonPointerItem::Number(idx)), Value::Null | Value::Bool(false)) => {
if let Some(key) = T::try_from_integer(*idx) {
let key = T::try_from_integer(*idx);
if !pointer.has_next()
&& let Some(key) = key
{
self.0.retain(|item| item != &key);
return Ok(MaybeUnpatched::Patched);
}
}
(Some(JsonPointerItem::Key(key)), Value::Null | Value::Bool(false)) => {
if let Some(key) = T::try_from_string(key.to_string().as_ref()) {
let key = T::try_from_string(key.to_string().as_ref());
if !pointer.has_next()
&& let Some(key) = key
{
self.0.retain(|item| item != &key);
return Ok(MaybeUnpatched::Patched);
}
}
(Some(JsonPointerItem::Key(key)), Value::Bool(true)) => {
if let Some(key) = T::try_from_string(key.to_string().as_ref()) {
let key = T::try_from_string(key.to_string().as_ref());
if !pointer.has_next()
&& let Some(key) = key
{
if !self.0.contains(&key) {
self.0.push(key);
}
@@ -161,7 +173,10 @@ impl<T: MapItem + Default> RegistryJsonPatch for Map<T> {
}
}
(Some(JsonPointerItem::Number(idx)), Value::Bool(true)) => {
if let Some(key) = T::try_from_integer(*idx) {
let key = T::try_from_integer(*idx);
if !pointer.has_next()
&& let Some(key) = key
{
if !self.0.contains(&key) {
self.0.push(key);
}