Skip to content

Commit e04d677

Browse files
committed
Treat empty _in arrays as false, ie.
1 parent a5735dd commit e04d677

3 files changed

Lines changed: 52 additions & 5 deletions

File tree

src/BccCode.Linq/Server/Filter.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,12 @@ private void _parse(string json)
112112
else if (new[] { "_in", "_nin" }.Contains(key))
113113
{
114114
var array = JsonConvert.DeserializeObject<T[]>(value.ToString() ?? string.Empty);
115-
if (array is null || array.Length == 0)
115+
// Treat empty arrays as a valid value (resulting in a predicate that's always false for _in
116+
// and always true for _nin). Only null is considered invalid.
117+
if (array is null)
116118
{
117119
throw new ArgumentException(
118-
$"JSON filter rule is invalid. Array under {key} is null or empty.");
120+
$"JSON filter rule is invalid. Array under {key} is null.");
119121
}
120122

121123
deserializedJson[key] = array;
@@ -135,12 +137,19 @@ private void _parse(string json)
135137
? typeof(ValueTuple<,>).MakeGenericType(propertyType, propertyType)
136138
: typeof(Tuple<,>).MakeGenericType(propertyType, propertyType);
137139

138-
deserializedJson[key] = Activator.CreateInstance(tupleType,
140+
var tupleInstance = Activator.CreateInstance(tupleType,
139141
OperandToExpressionResolver.ConvertValue(propertyInfo?.PropertyType ?? GetFilterType(),
140142
array[0].ToString()),
141143
OperandToExpressionResolver.ConvertValue(propertyInfo?.PropertyType ?? GetFilterType(),
142144
array[1].ToString())
143145
);
146+
147+
if (tupleInstance == null)
148+
{
149+
throw new InvalidOperationException($"Failed to create tuple instance for key {key}");
150+
}
151+
152+
deserializedJson[key] = tupleInstance;
144153
}
145154
else if (key.StartsWith("_"))
146155
{

tests/BccCode.Linq.Tests/FilterTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,12 @@ public void should_cast_value_to_decimal_list()
7777
}
7878

7979
[Fact]
80-
public void should_throw_exception_on_empty_list()
80+
public void should_allow_empty_list_in_in_operator()
8181
{
8282
var json = @"{ ""StringArrayProp"": { ""_in"": [] } }";
8383

84-
Assert.Throws<ArgumentException>(() => new Filter<TestClass>(json));
84+
var ex = Record.Exception(() => new Filter<TestClass>(json));
85+
Assert.Null(ex);
8586
}
8687

8788
[Fact]

tests/BccCode.Linq.Tests/Server/FilterToLambdaParserTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,41 @@ public void should_get_correct_result_when_filtering_nested_object()
111111

112112
Assert.Equal(expected.Count, result.Count);
113113
}
114+
115+
[Fact]
116+
public void should_match_using_in_operator()
117+
{
118+
var jsonRule = "{\n \"country\": { \n \"_in\": [\"Poland\", \"Greece\"]\n }\n}";
119+
120+
var expected = PeopleList.Where(person => new[] { "Poland", "Greece" }.Contains(person.Country)).ToList();
121+
var f = new Filter<Person>(jsonRule);
122+
var exp = FilterToLambdaParser.Parse(f);
123+
var result = PeopleList.Where(exp.Compile()).ToList();
124+
125+
Assert.Equal(expected.Count, result.Count);
126+
}
127+
128+
[Fact]
129+
public void empty_in_array_should_match_no_items()
130+
{
131+
var jsonRule = "{\n \"country\": { \n \"_in\": []\n }\n}";
132+
133+
var f = new Filter<Person>(jsonRule);
134+
var exp = FilterToLambdaParser.Parse(f);
135+
var result = PeopleList.Where(exp.Compile()).ToList();
136+
137+
Assert.Empty(result);
138+
}
139+
140+
[Fact]
141+
public void empty_nin_array_should_match_all_items()
142+
{
143+
var jsonRule = "{\n \"country\": { \n \"_nin\": []\n }\n}";
144+
145+
var f = new Filter<Person>(jsonRule);
146+
var exp = FilterToLambdaParser.Parse(f);
147+
var result = PeopleList.Where(exp.Compile()).ToList();
148+
149+
Assert.Equal(PeopleList.Count, result.Count);
150+
}
114151
}

0 commit comments

Comments
 (0)