Skip to content

Commit

Permalink
Merge pull request #5 from streamdal/blinktag/fix_delete_trailing_comma
Browse files Browse the repository at this point in the history
ENG-1605 - Fix trailing comma when deleting a key
  • Loading branch information
blinktag authored Feb 27, 2024
2 parents a26a90f + 57b2ae5 commit 3c05e76
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 6 deletions.
38 changes: 34 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1262,15 +1262,45 @@ pub fn delete_path<'a>(json: &'a str, path: &'a str) -> Result<String, GJSONErro
}
};


let value_len = existing_value.json().len();
let mut value_end = value_begin + value_len;

// Check if value_end + 1 character is a comma, if so, delete that also
if value_end + 1 < json.len() && json.as_bytes()[value_end] == b',' {
value_end += 1;
// gJSON returns a trailing comma if we select the first element of an object
// but does not for subsequent elements. We need to exclude this trailing comma
if json.as_bytes()[value_end] == b',' {
value_end += 1
}

// When deleting the last element from an object, a trailing comma will be present
// still on the previous element. We need to remove it by iterating backwards from the key_start
// First check if we're at the end of an object
if json.as_bytes()[value_end] == b'}' {
let mut i = key_start;
while i > 0 {
match json.as_bytes()[i] {
b'{' | b'[' => {
// We hit the beginning of an object or array, nothing to do
break;
},
b',' => {
// We hit the trailing comma of a previous element, return JSON without it
return Ok(format!("{}{}", &json[..i].trim(), &json[value_end..].trim()))
}
_ => {
// Do nothing
}
}
if json.as_bytes()[i] == b',' {
return Ok(format!("{}{}", &json[..i].trim(), &json[value_end..].trim()))
}
i -= 1;
}
}


eprint!("value_begin: '{}'\n", json.as_bytes()[value_begin] as char);
eprint!("value_end: '{}'\n", json.as_bytes()[value_end] as char);

// Trim both sides of where the "key":"value" was and concat it back together
Ok(format!("{}{}",&json[..key_start].trim(), &json[value_end..].trim()))
}
Expand Down
20 changes: 18 additions & 2 deletions src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,28 @@ fn index() {

#[test]
fn test_delete_path() {
let json = r#"{"object":{"subobject": {"field":" value" }}}"#;

// Only key in object
let json = r#"{"object":{"subobject": {"field":" value"}}}"#;
let want = r#"{"object":{"subobject": {}}}"#;
let got = delete_path(json, "object.subobject.field").unwrap();
assert_eq!(want, got);

// First key in object
let json = r#"{"object":{"subobject": {"field":" value", "some": "other"}}}"#;
let want = r#"{"object":{"subobject": {"some": "other"}}}"#;
let got = delete_path(json, "object.subobject.field").unwrap();
assert_eq!(want, got);

// Key in middle of object
let json = r#"{"object":{"subobject": {"field": "value", "some": "other", "another": "val"}}}"#;
let want = r#"{"object":{"subobject": {"field": "value","another": "val"}}}"#;
let got = delete_path(json, "object.subobject.some").unwrap();
assert_eq!(want, got);

// // Last key in object
let json = r#"{"object":{"subobject": {"field": "value", "some": "other", "another": "val"}}}"#;
let want = r#"{"object":{"subobject": {"field": "value", "some": "other"}}}"#;
let got = delete_path(json, "object.subobject.another").unwrap();
assert_eq!(want, got);
}

Expand Down

0 comments on commit 3c05e76

Please sign in to comment.