use std::io::Read;
use serde_json::Value;
pub fn resolve_json(raw: &str, what: &str) -> Result<Value, String> {
if raw == "-" {
let mut s = String::new();
std::io::stdin()
.read_to_string(&mut s)
.map_err(|e| format!("{what}: reading stdin: {e}"))?;
serde_json::from_str(&s).map_err(|e| format!("{what}: invalid JSON on stdin: {e}"))
} else if let Some(path) = raw.strip_prefix('@') {
let content = std::fs::read_to_string(path)
.map_err(|e| format!("{what}: reading {path}: {e}"))?;
serde_json::from_str(&content)
.map_err(|e| format!("{what}: invalid JSON in {path}: {e}"))
} else {
serde_json::from_str(raw).map_err(|e| format!("{what}: invalid JSON: {e}"))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_literal_json() {
let v = resolve_json(r#"{"a":1}"#, "x").unwrap();
assert_eq!(v["a"], 1);
}
#[test]
fn parses_file_json() {
let tmp = tempfile::tempdir().unwrap();
let path = tmp.path().join("input.json");
std::fs::write(&path, r#"{"b":"y"}"#).unwrap();
let arg = format!("@{}", path.display());
let v = resolve_json(&arg, "x").unwrap();
assert_eq!(v["b"], "y");
}
#[test]
fn invalid_literal_returns_helpful_error() {
let err = resolve_json("not json", "payload").unwrap_err();
assert!(err.contains("payload: invalid JSON"));
}
#[test]
fn missing_file_returns_helpful_error() {
let err = resolve_json("@/nonexistent/file", "payload").unwrap_err();
assert!(err.contains("reading"));
}
}