whipplescript_core/
json.rs1use serde_json::Value;
9
10pub fn required_json_string(value: &Value, field: &str, owner: &str) -> Result<String, String> {
13 value
14 .get(field)
15 .and_then(Value::as_str)
16 .filter(|value| !value.trim().is_empty())
17 .map(str::to_owned)
18 .ok_or_else(|| format!("{owner} must have non-empty `{field}` string"))
19}
20
21pub fn optional_json_string(value: &Value, field: &str) -> Option<String> {
23 value
24 .get(field)
25 .and_then(Value::as_str)
26 .filter(|value| !value.trim().is_empty())
27 .map(str::to_owned)
28}
29
30pub fn optional_json_string_any(value: &Value, fields: &[&str]) -> Option<String> {
32 fields
33 .iter()
34 .find_map(|field| optional_json_string(value, field))
35}
36
37pub fn optional_json_string_array(value: &Value, field: &str) -> Option<Vec<String>> {
39 value.get(field).and_then(Value::as_array).map(|items| {
40 items
41 .iter()
42 .filter_map(Value::as_str)
43 .filter(|item| !item.trim().is_empty())
44 .map(str::to_owned)
45 .collect::<Vec<_>>()
46 })
47}
48
49pub fn require_json_array_field<'a>(
51 value: &'a Value,
52 field: &str,
53 owner: &str,
54) -> Result<&'a Vec<Value>, String> {
55 value
56 .get(field)
57 .and_then(Value::as_array)
58 .ok_or_else(|| format!("{owner}.{field} must be an array"))
59}
60
61pub fn quoted_platform_values<'a>(values: impl IntoIterator<Item = &'a str>) -> String {
64 values
65 .into_iter()
66 .map(|value| format!("`{value}`"))
67 .collect::<Vec<_>>()
68 .join(", ")
69}