[JAVA-2173] add new Enum value for org.bson.json.JsonMode Created: 20/Apr/16  Updated: 09/Mar/17  Resolved: 09/Mar/17

Status: Closed
Project: Java Driver
Component/s: BSON
Affects Version/s: 3.0.0
Fix Version/s: None

Type: New Feature Priority: Minor - P4
Reporter: sun mingxin Assignee: Unassigned
Resolution: Won't Fix Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

All


Issue Links:
Related
related to JAVA-1772 Make it easier to change JsonWriter b... Closed
related to JAVA-2447 Implement Extended JSON specification Closed

 Description   

For below code

    Document("a", 12).append("b", 14l).toJson()

The output is

{ "a" : 12, "b" : { "$numberLong" : "14" } }

If we change code as

    Document("a", 12).append("b", 14l).toJson(new JsonWriterSettings(JsonMode.SHELL))

It generates

{ "a" : 12, "b" : NumberLong(14) }

However in some circumstance, we expect to get the simple

{ "a" : 12, "b" : 14 }.

In the implementation of JsonWriter.doWriteInt64(), there is a default switch case for such output, but it never goes there because JsonMode has only two exact enum value.

So please add one new enum value for JsonMode, and then we can write code as

    Document("a", 12).append("b", 14l).toJson(new JsonWriterSettings(JsonMode.NEW_VALUE))

and then can get the simple output

{ "a" : 12, "b" : 14 }



 Comments   
Comment by Jeffrey Yemin [ 09/Mar/17 ]

In scope of JAVA-1772 applications can now register customer converters in order to fine-tune JSON generation. To get the effect you've requested, one will be able to do:

        JsonWriterSettings settings = JsonWriterSettings.builder()
                                                 .int64Converter((value, writer) -> writer.writeNumber(value.toString()))
                                                 .build();
        String json = new Document("a", 12).append("b", 14L).toJson(settings);

Given this added flexibility, we no longer plan to add a new output mode for this use case.

Comment by Aleksey Korolev [ 09/Jun/16 ]

I stumbled upon the same problem after migrating my code from Java driver version 2.x to 3.x.
My application reads documents from MongoDB and send to another application as JSON strings where they are parsed using Jackson library.
After I changed usages of DBObject.toString() for Document.toJson() parsing with Jackson started to fail on extended Bson types.
Using JsonMode.STRICT fixed problem with everything but the presense of "$numberLong" type for long values.
By looking at the code in method org.bson.json.JsonWriter#doWriteInt64(long) below it is abvious that this is a bug: the default case is never reached.

   @Override
    protected void doWriteInt64(final long value) {
        try {
            switch (settings.getOutputMode()) {
                case STRICT:
                    writeStartDocument();
                    writeNameHelper("$numberLong");
                    writer.write(format("\"%d\"", value));
                    writeEndDocument();
                    break;
                case SHELL:
                    writeNameHelper(getName());
                    if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
                        writer.write(format("NumberLong(%d)", value));
                    } else {
                        writer.write(format("NumberLong(\"%d\")", value));
                    }
                    break;
                default:
                    writeNameHelper(getName());
                    writer.write(Long.toString(value));
                    break;
            }
        } catch (IOException e) {
            throwBSONException(e);
        }
    }

To my mind the code from default case branch must be moved to STRICT case branch.
Default case branch must be throwing BSONException("Unexpected JSONMode.") like in other methods e.g. doWriteTimestamp()

Comment by sun mingxin [ 22/Apr/16 ]

More seriously, it breaks the compatible. All existing client code are dealing

{ "a" : 12, "b" : 14 }

when we are using legacy DBObject, but now the server returns a complex string and client code fails.

Comment by sun mingxin [ 21/Apr/16 ]

So far we have no such issue. I go through the source again and find it will throw exception for object id and date type if the JsonMode is neither the two. So a better suggestion may be allowing customized writer to construct perferred output format.

Comment by Jeffrey Yemin [ 20/Apr/16 ]

Do you have any issues with the way other BSON types are represented as JSON? For instance, an ObjectId will look like this:

{ "$oid" : "4d0ce088e447ad08b4721a37" }

while a Date will look like this:

{ "$date" : 9223372036854775807 }

Generated at Thu Feb 08 08:56:31 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.