Extract value from JSON using simple path notation
(json: &JsonValue, path: &str)
| 1447 | |
| 1448 | /// Extract value from JSON using simple path notation |
| 1449 | fn extract_json_path(json: &JsonValue, path: &str) -> Option<JsonValue> { |
| 1450 | // Handle root path '$' |
| 1451 | if path == "$" { |
| 1452 | return Some(json.clone()); |
| 1453 | } |
| 1454 | |
| 1455 | // Handle paths starting with '$.' |
| 1456 | let path = if let Some(stripped) = path.strip_prefix("$.") { |
| 1457 | stripped |
| 1458 | } else if path.starts_with("$[") { |
| 1459 | &path[1..] |
| 1460 | } else { |
| 1461 | path |
| 1462 | }; |
| 1463 | |
| 1464 | // Handle array index at root level |
| 1465 | if path.starts_with("[") && path.ends_with("]") { |
| 1466 | if let JsonValue::Array(arr) = json { |
| 1467 | let index_str = &path[1..path.len()-1]; |
| 1468 | if let Ok(index) = index_str.parse::<usize>() { |
| 1469 | return arr.get(index).cloned(); |
| 1470 | } |
| 1471 | } |
| 1472 | return None; |
| 1473 | } |
| 1474 | |
| 1475 | let parts: Vec<&str> = path.split('.').filter(|s| !s.is_empty()).collect(); |
| 1476 | let mut current = json; |
| 1477 | |
| 1478 | for part in parts { |
| 1479 | if part.starts_with("[") && part.ends_with("]") { |
| 1480 | // Array index notation |
| 1481 | if let JsonValue::Array(arr) = current { |
| 1482 | let index_str = &part[1..part.len()-1]; |
| 1483 | if let Ok(index) = index_str.parse::<usize>() { |
| 1484 | current = arr.get(index)?; |
| 1485 | } else { |
| 1486 | return None; |
| 1487 | } |
| 1488 | } else { |
| 1489 | return None; |
| 1490 | } |
| 1491 | } else { |
| 1492 | match current { |
| 1493 | JsonValue::Object(map) => { |
| 1494 | current = map.get(part)?; |
| 1495 | } |
| 1496 | JsonValue::Array(arr) => { |
| 1497 | let index: usize = part.parse().ok()?; |
| 1498 | current = arr.get(index)?; |
| 1499 | } |
| 1500 | _ => return None, |
| 1501 | } |
| 1502 | } |
| 1503 | } |
| 1504 | |
| 1505 | Some(current.clone()) |
| 1506 | } |
no test coverage detected