Skip to content

JAVA-3292: Add a Codec for converting directly to and from a JSON string #572

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 19 commits into from

Conversation

bdeleonardis1
Copy link
Contributor

No description provided.

@bdeleonardis1 bdeleonardis1 requested a review from jyemin September 2, 2020 22:24
*
* @since 4.2
*/
public class JsonString {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I wasn't sure where to put this file. This folder contains json stuff, but it's not that related to the purpose of this file. I was debating between this folder and its parent folder.

  2. I decided against providing equals and hashcode methods because I thought users shouldn't really keep JsonStrings, they should just use them to access the string. Do you agree with this decision?

  3. I don't have any unit tests for this class. Is this okay for simple wrapper classes like this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I think this location is fine.

  2. I would add an equals and hashcode for comparison purposes - we don't know how users will use this class and if they will always unbox it directly.

  3. Yes lets add some unit tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@jyemin jyemin requested a review from rozza September 3, 2020 13:33
@bdeleonardis1
Copy link
Contributor Author

bdeleonardis1 commented Sep 3, 2020

Forgot to run a patch when I first put it up, here it is: https://spruce.mongodb.com/version/5f510b9c7742ae610dba68c5/tasks

Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments and nits.

* Construct a JsonStringCodec with default JsonWriterSettings
*/
public JsonStringCodec() {
this(JsonWriterSettings.builder().outputMode(JsonMode.RELAXED).build());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment (no action required): Seems odd to explicitly set the output mode when the javadoc notes its the default settings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you said no action required, but I agreed that this seemed weird so I got rid of setting the outputMode explicitly.

*
* @since 4.2
*/
public class JsonString {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I think this location is fine.

  2. I would add an equals and hashcode for comparison purposes - we don't know how users will use this class and if they will always unbox it directly.

  3. Yes lets add some unit tests.

package org.bson.json;

/**
* A wrapper class that holds a JSON string. This class makes decoding straight
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a note that it holds a JSON document String. As an array is a valid top level JSON type we should clarify.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

*
* @param json the JSON string
*/
public JsonString(final String json) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a not null check here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if a user tries to do:

MongoCollection<JsonString> collection.insert(new JsonString("['a', 'b', 'c']"));

Do you think there should be any validation on the String?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the null check.

I don't think we should verify if the String is valid JSON because that would hurt performance especially for large JSON strings and the whole purpose of this ticket is to improve performance. I decided to do a middle-ground where we check that the first and last characters are curly braces. My motivation is that this helps them catch obvious bugs where they try to pass in an array for example. My concern with this is that our constructor throws exceptions for certain invalid JSON inputs, but not others so this may be unpredictable to clients. What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I'm wondering if we should call this class something different. Since [1, 2, 3] (or even 1?) is valid JSON, should this class be called JsonObjectString instead, if indeed it will forever be restricted to JSON objects (see https://www.json.org/json-en.html)?

Even if we don't change the name, if we are committing to only supporting JSON objects, then this class can and should implement org.bson.conversions.Bson. That way, it can be used for query filters, etc.

Alternatively, we could allow any JSON string, not just JSON objects, though currently BsonReader.pipe currently only supports documents

Copy link
Contributor Author

@bdeleonardis1 bdeleonardis1 Sep 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (renamed to JsonObject and implements Bson)

*
* @param json the JSON string
*/
public JsonString(final String json) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I'm wondering if we should call this class something different. Since [1, 2, 3] (or even 1?) is valid JSON, should this class be called JsonObjectString instead, if indeed it will forever be restricted to JSON objects (see https://www.json.org/json-en.html)?

Even if we don't change the name, if we are committing to only supporting JSON objects, then this class can and should implement org.bson.conversions.Bson. That way, it can be used for query filters, etc.

Alternatively, we could allow any JSON string, not just JSON objects, though currently BsonReader.pipe currently only supports documents

Copy link
Collaborator

@jyemin jyemin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. I just have one more request for additional code coverage of the new whitespace checks.

* @param json the JSON object string
*/
public JsonObject(final String json) {
if (json == null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a notNull helper for this - see org.bson.assertions.Assertions.notNull

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

// Valid whitespace characters according to the json spec: https://www.json.org/json-en.html
if (c != 0x0020 && c != 0x000A && c != 0x000D && c != 0x0009) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use Character.isWhitespace as its what is actually used when parsing json strings and is probably more readable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommended this approach because it matches the JSON spec. Do you think that's not the behavior of most JSON parsers?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose, my thoughts were the only parser that actually matters is our own Json reader. Note we don't follow the strictness of the Json Spec, eg we support missing quotes / single quoted values, so thought Character.isWhitespace was more readable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing that Character.isWhitespace matches our own JsonReader's behavior, I agree with Ross and I changed it. Happy to change it back if you strongly disagree @jyemin .

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with this change. You can resolve this.

Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@jyemin
Copy link
Collaborator

jyemin commented Sep 11, 2020

LGTM!

@bdeleonardis1
Copy link
Contributor Author

Merged on command line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants