bguerout/jongo

Find query with field value containing a single quote not supported

Closed this issue · 6 comments

Hi all,

I have troubles using Jongo to run a find query with a value containing a single quote. I've tried escaping it in several ways:

With:

db.mycollection.find( {'someField': 'value with \' inside'} )

The result is:

java.lang.IllegalArgumentException: Cannot parse query: {'someField': 'value with ' inside'}
	at org.jongo.query.BsonQueryFactory.createQuery(BsonQueryFactory.java:168)
	at org.jongo.Find.<init>(Find.java:47)
	at org.jongo.MongoCollection.find(MongoCollection.java:90)
	at org.jongo.MongoCollection.find(MongoCollection.java:86)
(...)
Caused by: com.mongodb.util.JSONParseException: 
{'someField': 'value with ' inside'}
                            ^
	at com.mongodb.util.JSONParser.read(JSON.java:303)
	at com.mongodb.util.JSONParser.parseObject(JSON.java:274)
	at com.mongodb.util.JSONParser.parse(JSON.java:229)
	at com.mongodb.util.JSONParser.parse(JSON.java:157)
	at com.mongodb.util.JSON.parse(JSON.java:99)
	at org.jongo.query.BsonQueryFactory.createQuery(BsonQueryFactory.java:129)
	... 14 more

With:

db.mycollection.find( {'someField': 'value with \\\' inside'} )

The result is:

java.lang.IllegalArgumentException: Cannot parse query: {'someField': 'value with \' inside'}
	at org.jongo.query.BsonQueryFactory.createQuery(BsonQueryFactory.java:168)
	at org.jongo.Find.<init>(Find.java:47)
	at org.jongo.MongoCollection.find(MongoCollection.java:90)
	at org.jongo.MongoCollection.find(MongoCollection.java:86)
(...)
Caused by: com.mongodb.util.JSONParseException: 
{'someField': 'value with \' inside'}
                             ^
	at com.mongodb.util.JSONParser.read(JSON.java:303)
	at com.mongodb.util.JSONParser.parseObject(JSON.java:274)
	at com.mongodb.util.JSONParser.parse(JSON.java:229)
	at com.mongodb.util.JSONParser.parse(JSON.java:157)
	at com.mongodb.util.JSON.parse(JSON.java:99)
	at org.jongo.query.BsonQueryFactory.createQuery(BsonQueryFactory.java:129)
	... 14 more

Config:

  • Java 8
  • Jongo 1.4.0 and 1.5.0 SNAPSHOT, same behaviour
  • mongo-java-driver 3.10.1
  • jackson-core 2.9.8

This seems to be legal from MongoDB point of view, right?
Any ideas?

Thx in advance,
Franck.

Hi,

Just as a follow up, I've been investigating this issue. I came up with a workaround that works although it's pretty nasty honnestly.

So here is the thing: the MongoDB driver can deal with strings marked with double or single quotes.
It can deal with strings in double quotes with escaped double quotes inside: "ab \"cd\" ef"
But it does not support strings in single quotes with escaped quotes inside: 'O\'Connel'.

So, the workaround is, in Jongo, to replace all single quotes with double quotes except those that are escaped. Have a look at https://github.com/frmichel/jongo/blob/master/src/main/java/org/jongo/query/BsonQueryFactory.java lines 84-86.
Example: 'O\'Connel' is transformed into "O'Connel".

So in my use case, with simple find queries, that works fine. Here is an example (in Scala):

    // Note the \\ to escape the backslash, so that the string passed contains both characters:
    // a backslash followed by a single quote
    val q = "{'Lastname': 'O\\'Connel'}"
    var results = jongoContext.getCollection("mycollecion").find(q)

Problem: what are the possible side effects of such a change?? Honestly I don't know...

If you want I can submit a pull request for that.

Regards,
Franck.

Hi @bguerout, thx for your answer.

As a matter of fact, I must admit that I had not tried that. Since Jongo's guidelines say that strings should use single quotes, I just blindly complied to that. But indeed, using double quotes works fine like in {"someField": "value with ' inside"}.

Still, using strings with single quotes and escaping a single quote inside one string, like I was doing in {'someField': 'value with \' inside'}, still does not work, and that fails in MongoDB's driver.

Anyway, there is a workaround, and I'm happy with that. ;)

Franck.

As a workaround you can use a parameter # :

    @Test
    public void canBindAParameterWithSingleQuoteInParameter() throws Exception {

        collection.insert("{someField:#}", "value with ' inside");

        long nb = collection.count("{someField:#}", "value with ' inside");

        assertThat(nb).isEqualTo(1);
    }

Note that this is the same as using double quotes

H @bguerout, thx for the tip, however in my case the query comes from a configuration file, so that I can't use the '#' writing.

Franck.

stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.