Skip to content

Commit

Permalink
return null for first, last, nth on error
Browse files Browse the repository at this point in the history
Instead of empty string, return null value that's considered undefined
(and can be piped to the default filter) if the array is empty for the
filters first, last and nth. For nth, also change the out-of-bounds
value from empty string to null.

Closes #534, and is a breaking change.
  • Loading branch information
sooda committed Aug 11, 2020
1 parent 5dc12af commit c6ea10c
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
8 changes: 4 additions & 4 deletions docs/content/docs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -819,15 +819,15 @@ before `striptags`.

#### first
Returns the first element of an array.
If the array is empty, returns empty string.
If the array is empty, returns null (undefined) that can be chained to the default filter.

#### last
Returns the last element of an array.
If the array is empty, returns empty string.
If the array is empty, returns null (undefined) that can be chained to the default filter.

#### nth
Returns the nth element of an array.§
If the array is empty, returns empty string.
Returns the nth element of an array.
If the array is empty or if the nth is out of bounds, returns null (undefined) that can be chained to the default filter.
It takes a required `n` argument, corresponding to the 0-based index you want to get.

Example: `{{ value | nth(n=2) }}`
Expand Down
22 changes: 11 additions & 11 deletions src/builtins/filters/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,45 @@ use crate::filter_utils::{get_sort_strategy_for_type, get_unique_strategy_for_ty
use serde_json::value::{to_value, Map, Value};

/// Returns the nth value of an array
/// If the array is empty, returns empty string
/// If the array is empty, returns null
pub fn nth(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
let arr = try_get_value!("nth", "value", Vec<Value>, value);

if arr.is_empty() {
return Ok(to_value("").unwrap());
return Ok(Value::Null);
}

let index = match args.get("n") {
Some(val) => try_get_value!("nth", "n", usize, val),
None => return Err(Error::msg("The `nth` filter has to have an `n` argument")),
};

Ok(arr.get(index).unwrap_or(&to_value("").unwrap()).to_owned())
Ok(arr.get(index).map(|x| x.to_owned()).unwrap_or(Value::Null))
}

/// Returns the first value of an array
/// If the array is empty, returns empty string
/// If the array is empty, returns null
pub fn first(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let mut arr = try_get_value!("first", "value", Vec<Value>, value);

if arr.is_empty() {
Ok(to_value("").unwrap())
Ok(Value::Null)
} else {
Ok(arr.swap_remove(0))
}
}

/// Returns the last value of an array
/// If the array is empty, returns empty string
/// If the array is empty, returns null
pub fn last(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let mut arr = try_get_value!("last", "value", Vec<Value>, value);

Ok(arr.pop().unwrap_or_else(|| to_value("").unwrap()))
Ok(arr.pop().unwrap_or(Value::Null))
}

/// Joins all values in the array by the `sep` argument given
/// If no separator is given, it will use `""` (empty string) as separator
/// If the array is empty, returns empty string
/// If the array is empty, returns null
pub fn join(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
let arr = try_get_value!("join", "value", Vec<Value>, value);
let sep = match args.get("sep") {
Expand Down Expand Up @@ -319,7 +319,7 @@ mod tests {
args.insert("n".to_string(), to_value(1).unwrap());
let result = nth(&to_value(&v).unwrap(), &args);
assert!(result.is_ok());
assert_eq!(result.unwrap(), to_value("").unwrap());
assert_eq!(result.unwrap(), Value::Null);
}

#[test]
Expand All @@ -335,7 +335,7 @@ mod tests {

let result = first(&to_value(&v).unwrap(), &HashMap::new());
assert!(result.is_ok());
assert_eq!(result.ok().unwrap(), to_value("").unwrap());
assert_eq!(result.ok().unwrap(), Value::Null);
}

#[test]
Expand All @@ -351,7 +351,7 @@ mod tests {

let result = last(&to_value(&v).unwrap(), &HashMap::new());
assert!(result.is_ok());
assert_eq!(result.ok().unwrap(), to_value("").unwrap());
assert_eq!(result.ok().unwrap(), Value::Null);
}

#[test]
Expand Down

0 comments on commit c6ea10c

Please sign in to comment.