[CSHARP-482] JSON serialized ObjectID can't be deserialized back Created: 30/May/12  Updated: 20/Mar/14  Resolved: 30/May/12

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 1.4.2
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Swell Assignee: Robert Stam
Resolution: Done Votes: 0
Labels: driver
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

.Net 4.5, Windows 7, C# driver 1.4.2



 Description   

Here is a small console application to reproduce the bug

namespace ConsoleApplication1
{
class Program
{
class A
{
public ObjectId Id

{ get; set; }
public string Name { get; set; }

public int counter

{ get; set; }

}
static void Main(string[] args)
{
var a = new A()

{ Id = ObjectId.GenerateNewId(), Name = "Test1", counter = 1 }

;
JavaScriptSerializer json = new JavaScriptSerializer();
var s = json.Serialize(a);
var b = json.Deserialize<A>(s);
}
}
}

a and b are different. b does match Name and counter field but Id are different.

A.Id = 4fc68f495669bd1ba000e831
B.Id = 000000000000000000000000

s = {\"Id\":

{\"Timestamp\":1338412873,\"Machine\":5663165,\"Pid\":7072,\"Increment\":59441,\"CreationTime\":\"\\/Date(1338412873000)\\/\"}

,\"Name\":\"Test1\",\"counter\":1}

FYI, python serialized ObjectId looks like this:
>>> json.dumps(d, default=json_util.default)

'{"_id":

{"$oid": "4fc68f495669bd1ba000e831"}

, "Name": "Test1", "counter":1}'

Do you think JSON serialized ObjectId can match between drivers? (GUID JSON output are also different between drivers)



 Comments   
Comment by Swell [ 31/May/12 ]

@Craig, you are right and I will follow 2) (I alrealy have in fact guid in my actual object).
I don't get why the serialization/deserialization does not produce the original object . If you think that it is unrelated to MongoDB, I will try to get in touch with MS as it sounds me very bad that these operations are not propertly working together.

Comment by Craig Wilson [ 31/May/12 ]

@Swell, as a matter of principle and compatibility, I'd suggest you do one of two things: 1) don't use ObjectId, or any MongoDB specific type as it is unlikely a client of your REST service will understand. Instead use a Guid. Or 2) Create an actual RESTful resource that gets mapped to and from your data object. It is highly unlikely that your MongoDB data entities map to proper RESTful resources as they are most likely missing hypermedia. Hence, you'll need some form of mapping to enhance your objects before sending them over the wire.

Comment by Robert Stam [ 30/May/12 ]

The JsonWriter has different output modes: Strict, JavaScript, TenGen and Shell. The default output mode is Shell, which is the most readable and is compatible with the mongo shell. Strict is the most conservative and produces output that is strictly compatible with the JSON standard. To use a different output mode you can do this:

var jsonSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict };
var s = a.ToJson(jsonSettings);
var b = BsonSerializer.Deserialize<A>(s);

You can read more about the different output modes at:

http://www.mongodb.org/display/DOCS/Mongo+Extended+JSON

These extensions are required because BSON has data types that strict JSON doesn't support.

Comment by Swell [ 30/May/12 ]

Thx Robert.

I have tried your advice and It works now ( a == b ). However the serialized version does not look as a valid JSON string

{ "_id" : ObjectId("4fc696d45669bd3a242818d9"), "Name" : "Test1", "counter" : 1 }

as ObjectId("4fc696d45669bd3a242818d9") will not be properly understood by a javasript client ( I am building a browser application that use a REST service to CRUD data in a Mongo Server).

Furthermore being able to have the same output format between C# driver and Pÿthon would be great.

Comment by Robert Stam [ 30/May/12 ]

We have no control over how the JavaScriptSerializer class works because it's part of .NET.

Have you tried using the JSON support built-in to the C# driver? It knows about the BSON types that are not part of standard JSON.

Using the C# driver's JSON support your code would look like this:

var s = a.ToJson();
var b = BsonSerializer.Deserialize<A>(s);

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