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 da6bf8cb7..b8258529c 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 @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.TimeZone; +import java.util.UUID; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -289,10 +290,9 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { } else if ("DBPointer".equals(value)) { setCurrentBsonType(BsonType.DB_POINTER); currentValue = visitDBPointerConstructor(); - } else if ("UUID".equals(value) || "GUID".equals(value) || "CSUUID".equals(value) || "CSGUID".equals(value) - || "JUUID".equals(value) || "JGUID".equals(value) || "PYUUID".equals(value) || "PYGUID".equals(value)) { + } else if ("UUID".equals(value)) { setCurrentBsonType(BsonType.BINARY); - currentValue = visitUUIDConstructor(value); + currentValue = visitUUIDConstructor(); } else if ("new".equals(value)) { visitNew(); } else { @@ -840,9 +840,8 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { } else if ("DBPointer".equals(value)) { currentValue = visitDBPointerConstructor(); setCurrentBsonType(BsonType.DB_POINTER); - } else if ("UUID".equals(value) || "GUID".equals(value) || "CSUUID".equals(value) || "CSGUID".equals(value) - || "JUUID".equals(value) || "JGUID".equals(value) || "PYUUID".equals(value) || "PYGUID".equals(value)) { - currentValue = visitUUIDConstructor(value); + } else if ("UUID".equals(value)) { + currentValue = visitUUIDConstructor(); setCurrentBsonType(BsonType.BINARY); } else { throw new JsonParseException("JSON reader expected a type name but found '%s'.", value); @@ -862,7 +861,13 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { setCurrentBsonType(BsonType.BINARY); return; } - } else if ("$regex".equals(value) || "$options".equals(value)) { + } + if ("$uuid".equals(value)) { + currentValue = visitUuidExtendedJson(); + setCurrentBsonType(BsonType.BINARY); + return; + } + else if ("$regex".equals(value) || "$options".equals(value)) { currentValue = visitRegularExpressionExtendedJson(value); if (currentValue != null) { setCurrentBsonType(BsonType.REGULAR_EXPRESSION); @@ -956,16 +961,12 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { return new BsonBinary(subTypeToken.getValue(Integer.class).byteValue(), bytes); } - private BsonBinary visitUUIDConstructor(final String uuidConstructorName) { - verifyToken(JsonTokenType.LEFT_PAREN); - String hexString = readStringFromExtendedJson().replaceAll("\\{", "").replaceAll("}", "").replaceAll("-", ""); - verifyToken(JsonTokenType.RIGHT_PAREN); - byte[] bytes = decodeHex(hexString); - BsonBinarySubType subType = BsonBinarySubType.UUID_STANDARD; - if (!"UUID".equals(uuidConstructorName) || !"GUID".equals(uuidConstructorName)) { - subType = BsonBinarySubType.UUID_LEGACY; - } - return new BsonBinary(subType, bytes); + private BsonBinary visitUUIDConstructor() { + this.verifyToken(JsonTokenType.LEFT_PAREN); + String hexString = this.readStringFromExtendedJson().replace("-", ""); + + this.verifyToken(JsonTokenType.RIGHT_PAREN); + return new BsonBinary(BsonBinarySubType.UUID_STANDARD, decodeHex(hexString)); } private BsonRegularExpression visitRegularExpressionConstructor() { @@ -1484,6 +1485,17 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { return value; } + private BsonBinary visitUuidExtendedJson() { + verifyToken(JsonTokenType.COLON); + String hexString = this.readStringFromExtendedJson().replace("-", ""); + verifyToken(JsonTokenType.END_OBJECT); + try { + return new BsonBinary(BsonBinarySubType.UUID_STANDARD, decodeHex(hexString)); + } catch (IllegalArgumentException e) { + throw new JsonParseException(e); + } + } + private void visitJavaScriptExtendedJson() { verifyToken(JsonTokenType.COLON); String code = readStringFromExtendedJson(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index bd82d7d7d..cf2dceed7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -27,6 +27,8 @@ import java.util.Date; import java.util.List; import java.util.UUID; +import org.bson.BsonBinary; +import org.bson.BsonBinarySubType; import org.bson.Document; import org.bson.codecs.DecoderContext; import org.junit.jupiter.api.Test; @@ -547,6 +549,23 @@ class ParameterBindingJsonReaderUnitTests { assertThat(target.get("arg0")).isEqualTo(source); } + @Test // GH-3750 + void shouldParseUUIDasStandardRepresentation() { + + String json = "{ 'value' : UUID(\"b5f21e0c-2a0d-42d6-ad03-d827008d8ab6\") }"; + + BsonBinary value = parse(json).get("value", BsonBinary.class); + assertThat(value.getType()).isEqualTo(BsonBinarySubType.UUID_STANDARD.getValue()); + } + + @Test // GH-3750 + public void shouldParse$uuidAsStandardRepresentation() { + + String json = "{ 'value' : { '$uuid' : \"73ff-d26444b-34c6-990e8e-7d1dfc035d4\" } } }"; + BsonBinary value = parse(json).get("value", BsonBinary.class); + assertThat(value.getType()).isEqualTo(BsonBinarySubType.UUID_STANDARD.getValue()); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args);