From 007b6d4f986cd1188810042588273e7b57572eab Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 1 Mar 2019 08:38:47 +0100 Subject: [PATCH] DATAMONGO-1593 - Fix JSON parsing for $oid in String based queries. We now parse String arguments bound to an $oid correctly, so that those end up as valid ObjectId. @Query("{ 'arg0' : { '$oid' : ?0} }") List singeObjectIdArgInQueryString(String arg0); Original pull request: #652. --- .../util/json/ParameterBindingJsonReader.java | 11 +++-- .../query/StringBasedMongoQueryUnitTests.java | 41 +++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index fc385729a..7f5e50d5e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -1326,12 +1326,15 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { private String readStringFromExtendedJson() { JsonToken patternToken = popToken(); - if (patternToken.getType() != JsonTokenType.STRING) { - throw new JsonParseException("JSON reader expected a string but found '%s'.", patternToken.getValue()); - } // Spring Data Customization START - return bindableValueFor(patternToken).getValue().toString(); + + if (patternToken.getType() == JsonTokenType.STRING || patternToken.getType() == JsonTokenType.UNQUOTED_STRING) { + return bindableValueFor(patternToken).getValue().toString(); + } + + throw new JsonParseException("JSON reader expected a string but found '%s'.", patternToken.getValue()); + // Spring Data Customization END } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index 92c3fe8fb..1928eef6a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -29,8 +29,10 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import org.assertj.core.api.Assertions; import org.bson.BSON; import org.bson.Document; +import org.bson.types.ObjectId; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -614,6 +616,39 @@ public class StringBasedMongoQueryUnitTests { assertThat(query.getFieldsObject(), is(equalTo(Document.parse("{ \"fans\" : { \"$slice\" : [0, 5] } }")))); } + @Test // DATAMONGO-1593 + public void shouldRenderObjectIdParameterCorrectly() { + + ObjectId id = new ObjectId(); + + StringBasedMongoQuery mongoQuery = createQueryForMethod("singeObjectIdArgInQueryString", String.class); + ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, id.toString()); + + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); + Assertions.assertThat(query.getQueryObject()).isEqualTo(new Document("arg0", id)); + } + + @Test // DATAMONGO-1593 + public void shouldRenderMultipleObjectIdParametersCorrectly() { + + ObjectId id = new ObjectId(); + ObjectId readUsersId = new ObjectId(); + + StringBasedMongoQuery mongoQuery = createQueryForMethod("multipleObjectIdArgsInQueryString", String.class, + String.class); + + ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, id.toString(), + readUsersId.toString()); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); + + Assertions.assertThat(query.getQueryObject().get("arg0")).isEqualTo(id); + Assertions.assertThat(query.getQueryObject().get("$or")).isInstanceOf(List.class); + Assertions.assertThat(DocumentTestUtils.getAsDBList(query.getQueryObject(), "$or").get(0)) + .isEqualTo(new Document("arg1.value0", readUsersId)); + Assertions.assertThat(DocumentTestUtils.getAsDBList(query.getQueryObject(), "$or").get(1)) + .isEqualTo(new Document("arg1.value1", readUsersId)); + } + private StringBasedMongoQuery createQueryForMethod(String name, Class... parameters) { try { @@ -732,6 +767,12 @@ public class StringBasedMongoQueryUnitTests { @Query(value = "{ 'id' : ?0 }", fields = "{ 'fans': { '$slice': [ ?1, ?2 ] } }") Person findWithSliceInProjection(String id, int skip, int limit); + + @Query("{ 'arg0' : { \"$oid\" : ?0} }") + List singeObjectIdArgInQueryString(String arg0); + + @Query("{ 'arg0' : { \"$oid\" : ?0} , '$or' : [ { 'arg1.value0' : { \"$oid\" : ?1 } }, { 'arg1.value1' : { \"$oid\" : ?1 } } ] }") + List multipleObjectIdArgsInQueryString(String arg0, String arg1); } }