[CSHARP-2602] JsonOutputMode.Shell should output NumberInt(12345) for int32 types Created: 03/May/19  Updated: 31/Mar/22

Status: Backlog
Project: C# Driver
Component/s: Json
Affects Version/s: 2.11.0
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Cody Gibson Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows 10, C#



 Description   

I'm trying to convert a BsonDocument to a JSON string that MongoShell can correctly interpret. I'm not getting the expected results. Here's my sample code to reproduce the issue: 

public static void Main()
{
    var json = "{\"myinteger\" : 12345 }";
    var bsonDocument = BsonDocument.Parse(json);
    if (!bsonDocument["myinteger"].IsInt32)
        throw new ApplicationException("myInteger element is not an int32");
    var settings = new JsonWriterSettings { OutputMode = JsonOutputMode.Shell };
    var mainJson = bsonDocument.ToJson(settings);
}

This is just a very small part of the code that is trying to generate MongoShell commands to update a MongoDB database. What I get stored in mainJson is this: 

{ "myinteger" : 12345 }

 What I expected is this: 

{ "myinteger" : NumberInt(12345) }

Notice that NumberInt is missing.

This is a critical difference because MongoShell will interpret the first as a floating point number and store it as a floating point number when doing a $set, but will correctly interpret the second as an int32 and store it as an int32 when doing a $set.

I'm using the latest official MongoDB C# NuGet driver, version 2.8.0. Is it possible I've found a bug in ToJson() or am I just missing something?



 Comments   
Comment by Cody Gibson [ 15/May/19 ]

@Jeff Yemin, I work in a testing team. We are writing Selenium based tests to test our main web application. We use MongoDB to store the data the tests consume while running the tests. To manage data changes, we have 2 copies of the DB. One copy is considered our "master" which tests running on our build system pull from. When an SDET needs to change the input data, they will make their changes in a sandbox copy of the DB.

Now comes the problem, how do we get the changes the SDET's have made in the sandbox integrated into our master DB. This is what the tool I'm writing is attempting to solve. My tool will compare the master DB to the sandbox DB and will output MongoShell commands that can be used to update the master DB to incorporate the changes made to the sandbox DB.

The output of my tool (to be run by an SDET) will be put into merge request that an SDET will create. Once the merge request is approved (following code and data reviews) then whoever is doing the code merge must execute the MongoShell commands in order to update the master DB. That's why it's critical that the output from my tool must be correctly consumed/interpreted by MongoShell.

 

That help clarify my end goal?

Comment by Jeffrey Yemin [ 15/May/19 ]

The driver is open source so there is always a paddle available. You can fork the driver and make it work as you wish.

I'm also curious: what is the use case for this? If you're already in a .NET environment, why do you need this sort of integration with the MongoDB shell.

Comment by Cody Gibson [ 15/May/19 ]

So @Jeff.Yemin So are you implying that I'm "up a creek w/o a paddle"? How do I solve my problem today?

Comment by Jeffrey Yemin [ 13/May/19 ]

We don't currently have a Converter API for the .NET driver but I believe there is some planned work to do so.

Comment by Jeffrey Yemin [ 13/May/19 ]

Java driver works the same as .NET currently, though with the Converter API it's easy to change. This:

        System.out.println(new BsonDocument("x", new BsonInt32(1))
                .toJson(JsonWriterSettings.builder()
                        .outputMode(JsonMode.SHELL)
                        .int32Converter((value, writer) ->
                                writer.writeRaw(format("NumberInt(%d)", value)))
                        .build()));

Prints:

{"x": NumberInt(1)} 

Comment by Ian Whalen (Inactive) [ 13/May/19 ]

Hey sircody01 the shell is actually not consistent about this either. As an example:

MongoDB Enterprise > db.test.insert({x : NumberInt(1)})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise > db.test.findOne()
{ "_id" : ObjectId("5cd98280f6bcdf9cc0ab7c86"), "x" : 1 }

jeff.yemin to investigate what Java does first.

Generated at Wed Feb 07 21:43:00 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.