Skip to content

Commit 5c4515c

Browse files
authored
fix: optional filters deserialization (#803)
* fix optionalFilters deserialization * add tests
1 parent 461c23f commit 5c4515c

File tree

3 files changed

+63
-20
lines changed

3 files changed

+63
-20
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ _ReSharper*
5959
*.ncrunch*
6060
.*crunch*.local.xml
6161

62-
# Installshield output folder
62+
# Installshield output folder
6363
[Ee]xpress
6464

6565
# DocProject is a documentation generator add-in
@@ -109,5 +109,6 @@ UpgradeLog*.XML
109109
*.nupkg
110110

111111
# IDE
112+
.idea/
112113
.vscode/
113114
.vs/

src/Algolia.Search.Test/Serializer/SerializerTest.cs

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -198,23 +198,29 @@ public void TestAutomaticFacetFilters()
198198
[Parallelizable]
199199
public void TestLegacyFilterFormats()
200200
{
201-
// Testing "one string" legacy filters => should be converted to "ORED" nested filters
202-
// [["color:green","color:yellow"]]
201+
// Testing "one string" legacy filters => should be converted to "ANDED" nested filters
202+
// [["color:green"],["color:yellow"]]
203203
string stringFilters = "\"color:green,color:yellow\"";
204204

205205
var serializedStringFilters =
206206
JsonConvert.DeserializeObject<List<List<string>>>(stringFilters, new FiltersConverter());
207207

208-
AssertOredResult(serializedStringFilters);
208+
AssertAndedResult(serializedStringFilters, "color:green", "color:yellow");
209209

210-
// Testing "one array" legacy filters => should be converted to "ORED" nested filters
211-
// [["color:green","color:yellow"]]
210+
// Testing "one array" legacy filters => should be converted to "ANDED" nested filters
211+
// [["color:green"],["color:yellow"]]
212212
string arrayFilters = "[\"color:green\",\"color:yellow\"]";
213213

214214
var serializedArrayFilter =
215215
JsonConvert.DeserializeObject<List<List<string>>>(arrayFilters, new FiltersConverter());
216216

217-
AssertOredResult(serializedArrayFilter);
217+
AssertAndedResult(serializedArrayFilter, "color:green", "color:yellow");
218+
219+
// Strings inside an array should not be modified (i.e. not split into AND filter)
220+
string arrayFilters2 = "[\"color:green,color:yellow\",\"color:blue\"]";
221+
var serializedArrayFilter2 =
222+
JsonConvert.DeserializeObject<List<List<string>>>(arrayFilters2, new FiltersConverter());
223+
AssertAndedResult(serializedArrayFilter2, "color:green,color:yellow", "color:blue");
218224

219225
string nestedArrayFilters = "[[\"color:green\",\"color:yellow\"]]";
220226

@@ -223,18 +229,20 @@ public void TestLegacyFilterFormats()
223229

224230
AssertOredResult(serializedNestedArrayFilter);
225231

232+
// Testing "one string with parenthesis" legacy filters => should be converted to "ORED" filters
233+
// [["color:green", "color:yellow"], ["color:blue"]]
234+
string stringParenthesisFilters = "\"(color:green,color:yellow),color:blue\"";
235+
var serializedStringParenthesisFilters =
236+
JsonConvert.DeserializeObject<List<List<string>>>(stringParenthesisFilters, new FiltersConverter());
237+
AssertOredLatestResult(serializedStringParenthesisFilters, "color:green", "color:yellow", "color:blue");
238+
226239
// Testing the latest format of filters i.e nested arrays
227240
string nestedAndedArrayFilters = "[[\"color:green\",\"color:yellow\"],[\"color:blue\"]]";
228241

229-
var serializedAdedNestedArrayFilter =
242+
var serializedAndedNestedArrayFilter =
230243
JsonConvert.DeserializeObject<List<List<string>>>(nestedAndedArrayFilters, new FiltersConverter());
231244

232-
Assert.That(serializedAdedNestedArrayFilter, Has.Count.EqualTo(2));
233-
Assert.That(serializedAdedNestedArrayFilter.ElementAt(0), Has.Count.EqualTo(2));
234-
Assert.That(serializedAdedNestedArrayFilter.ElementAt(0).ElementAt(0), Contains.Substring("color:green"));
235-
Assert.That(serializedAdedNestedArrayFilter.ElementAt(0).ElementAt(1), Contains.Substring("color:yellow"));
236-
Assert.That(serializedAdedNestedArrayFilter.ElementAt(1), Has.Count.EqualTo(1));
237-
Assert.That(serializedAdedNestedArrayFilter.ElementAt(1).ElementAt(0), Contains.Substring("color:blue"));
245+
AssertOredLatestResult(serializedAndedNestedArrayFilter, "color:green", "color:yellow", "color:blue");
238246

239247
// Finally, testing that the custom reader is not breaking current implementation
240248
Rule ruleWithFilters = new Rule
@@ -293,6 +301,25 @@ void AssertOredResult(List<List<string>> result)
293301
Assert.That(result.ElementAt(0).ElementAt(0), Contains.Substring("color:green"));
294302
Assert.That(result.ElementAt(0).ElementAt(1), Contains.Substring("color:yellow"));
295303
}
304+
305+
void AssertAndedResult(List<List<string>> result, string expectedElement1, string expectedElement2)
306+
{
307+
Assert.That(result, Has.Count.EqualTo(2));
308+
Assert.That(result.ElementAt(0), Has.Count.EqualTo(1));
309+
Assert.That(result.ElementAt(0).ElementAt(0), Contains.Substring(expectedElement1));
310+
Assert.That(result.ElementAt(1), Has.Count.EqualTo(1));
311+
Assert.That(result.ElementAt(1).ElementAt(0), Contains.Substring(expectedElement2));
312+
}
313+
314+
void AssertOredLatestResult(List<List<string>> result, string expectedAnd1, string expectedAnd2, string expectedOr)
315+
{
316+
Assert.That(result, Has.Count.EqualTo(2));
317+
Assert.That(result.ElementAt(0), Has.Count.EqualTo(2));
318+
Assert.That(result.ElementAt(0).ElementAt(0), Contains.Substring(expectedAnd1));
319+
Assert.That(result.ElementAt(0).ElementAt(1), Contains.Substring(expectedAnd2));
320+
Assert.That(result.ElementAt(1), Has.Count.EqualTo(1));
321+
Assert.That(result.ElementAt(1).ElementAt(0), Contains.Substring(expectedOr));
322+
}
296323
}
297324

298325
[Test]

src/Algolia.Search/Serializer/FiltersConverter.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ public override IEnumerable<IEnumerable<string>> ReadJson(JsonReader reader, Typ
5959
{
6060
JToken token = JToken.Load(reader);
6161
var ret = new List<List<string>>();
62-
var tmpList = new List<string>();
6362

6463
foreach (var tokenValue in token)
6564
{
@@ -68,7 +67,7 @@ public override IEnumerable<IEnumerable<string>> ReadJson(JsonReader reader, Typ
6867
case JTokenType.Null:
6968
break;
7069
case JTokenType.String:
71-
tmpList.Add(tokenValue.ToObject<string>());
70+
ret.Add(new List<string> { tokenValue.ToObject<string>() });
7271
break;
7372
case JTokenType.Array:
7473
var jArray = (JArray)tokenValue;
@@ -77,19 +76,35 @@ public override IEnumerable<IEnumerable<string>> ReadJson(JsonReader reader, Typ
7776
}
7877
}
7978

80-
if (tmpList.Count > 0)
81-
ret.Add(tmpList);
82-
8379
return ret;
8480
}
8581

8682
if (reader.TokenType == JsonToken.String)
87-
return new List<List<string>> { Convert.ToString(reader.Value).Split(',').ToList() };
83+
return buildFilters(Convert.ToString(reader.Value)).ToList();
8884

8985
throw new JsonSerializationException(
9086
$"Error while reading Token {reader.Value} of type {reader.TokenType}.");
9187
}
9288

89+
/** Build filters from (legacy) string */
90+
private IEnumerable<List<string>> buildFilters(string str)
91+
{
92+
// Extract groups: "(A:1,B:2),C:3" -> ["(A:1,B:2)","C:3"]
93+
var groups = System.Text.RegularExpressions.Regex.Split(str, ",(?![^()]*\\))");
94+
return groups.Select(group =>
95+
{
96+
if (group.StartsWith("(") && group.EndsWith(")"))
97+
{
98+
var input = group.Substring(1, group.Length - 1);
99+
return input.Split(',').ToList();
100+
}
101+
else
102+
{
103+
return new List<string> { group };
104+
}
105+
});
106+
}
107+
93108
/// <summary>
94109
/// Disable write json
95110
/// </summary>

0 commit comments

Comments
 (0)