diff --git a/algoliasearch-core/src/main/java/com/algolia/search/models/indexing/FiltersJsonDeserializer.java b/algoliasearch-core/src/main/java/com/algolia/search/models/indexing/FiltersJsonDeserializer.java index 53f61af10..594566e3a 100644 --- a/algoliasearch-core/src/main/java/com/algolia/search/models/indexing/FiltersJsonDeserializer.java +++ b/algoliasearch-core/src/main/java/com/algolia/search/models/indexing/FiltersJsonDeserializer.java @@ -29,15 +29,12 @@ public List> deserialize(JsonParser p, DeserializationContext ctxt) switch (currentToken) { case START_ARRAY: - List list = p.readValueAs(List.class); - if (list.stream().allMatch(String.class::isInstance)) { // are all elements strings? - result = Collections.singletonList(list); - } else { - result = buildFilters(list); - } + List list = p.readValueAs(List.class); + result = buildFilters(list); break; case VALUE_STRING: - result = Collections.singletonList(Arrays.asList(p.getValueAsString().split(","))); + String string = p.getValueAsString(); + result = buildFilters(string); break; case VALUE_NULL: break; @@ -49,6 +46,7 @@ public List> deserialize(JsonParser p, DeserializationContext ctxt) return result; } + /** Build filters from a list */ @SuppressWarnings("unchecked") private List> buildFilters(List list) { return (List>) @@ -63,4 +61,21 @@ private List> buildFilters(List list) { }) .collect(Collectors.toList()); } + + /** Build filters from (legacy) string */ + private List> buildFilters(String string) { + // Extract groups: "(A:1,B:2),C:3" -> ["(A:1,B:2)","C:3"] + List groups = Arrays.asList(string.split(",(?![^()]*\\))")); + return groups.stream() + .map( + group -> { + if (group.startsWith("(") && group.endsWith(")")) { + String input = group.substring(1, group.length() - 1); + return Arrays.asList(input.split(",")); + } else { + return Collections.singletonList(group); + } + }) + .collect(Collectors.toList()); + } } diff --git a/algoliasearch-core/src/test/java/com/algolia/search/JacksonParserTest.java b/algoliasearch-core/src/test/java/com/algolia/search/JacksonParserTest.java index 011872e30..db1c4c757 100644 --- a/algoliasearch-core/src/test/java/com/algolia/search/JacksonParserTest.java +++ b/algoliasearch-core/src/test/java/com/algolia/search/JacksonParserTest.java @@ -171,18 +171,17 @@ void serializeFacetFilters() throws IOException { @ValueSource(strings = {"facetFilters", "optionalFilters", "tagFilters", "numericFilters"}) void testLegacyFiltersFormat(String input) throws IOException { - // Testing "one string" legacy filters => should be converted to "ORED" nested filters - // [["color:green","color:yellow"]] + // Testing "one string" legacy filters => should be converted to "ANDED" filters + // [["color:green"],["color:yellow"]] String stringFilters = String.format("{\"%s\":\"color:green,color:yellow\"}", input); - - assertOREDResult( + assertANDEDListResult( extractFilters( Defaults.getObjectMapper().readValue(stringFilters, ConsequenceParams.class), input)); - // Testing "one array" legacy filters => should be converted to "ORED" nested filters - // [["color:green","color:yellow"]] + // Testing "one array" legacy filters => should be converted to "ANDED" filters + // [["color:green"],["color:yellow"]] String arrayFilters = String.format("{\"%s\":[\"color:green\",\"color:yellow\"]}", input); - assertOREDResult( + assertANDEDListResult( extractFilters( Defaults.getObjectMapper().readValue(arrayFilters, ConsequenceParams.class), input)); @@ -193,8 +192,17 @@ void testLegacyFiltersFormat(String input) throws IOException { Defaults.getObjectMapper().readValue(nestedArrayFilters, ConsequenceParams.class), input)); + // Testing "one string with parenthesis" legacy filters => should be converted to "ORED" filters + // [["color:green", "color:yellow"], ["color:blue"]] + String stringParenthesisFilters = + String.format("{\"%s\":\"(color:green,color:yellow),color:blue\"}", input); + assertOREDLatestResult( + extractFilters( + Defaults.getObjectMapper().readValue(stringParenthesisFilters, ConsequenceParams.class), + input)); + // Testing mixed case with array and string - // [["color:green","color:yellow"],"color:blue"] + // [["color:green","color:yellow"], ["color:blue"]] String stringAndArrayFilters = String.format("{\"%s\":[[\"color:green\",\"color:yellow\"],\"color:blue\"]}", input); List> mixedDeserialized = @@ -242,6 +250,14 @@ void assertOREDResult(List> result) { assertThat(result.get(0)).containsSequence("color:yellow"); } + void assertANDEDListResult(List> result) { + assertThat(result).hasSize(2); + assertThat(result.get(0)).hasSize(1); + assertThat(result.get(0)).containsSequence("color:green"); + assertThat(result.get(1)).hasSize(1); + assertThat(result.get(1)).containsSequence("color:yellow"); + } + void assertOREDLatestResult(List> result) { assertThat(result).hasSize(2); assertThat(result.get(0)).hasSize(2);