I have an object
{
\"_id\": \"testobject\",
\"A\": \"First line\",
\"B\": \"Second line\",
\"C\": \"Third line\"
}
I want to send a RE
Not sure anyone is here >= June '20 however I did the following. I'm using NewtonSoft JObject/JArray and I wanted to create a mongo update parser/function that wouldn't know the incoming schema and would build out nested documents as well. Another thing I had to get used to (I'm new to Mongo) was the syntax of the keys in the Bson Update document i.e.
{ "key.full.path.into.nested.document" : "valueToSet" }
So, after trying a few ways to manually/recursively account for the nesting/containing path of incoming JSON doc, I finally found and can just use JToken.Path property perfectly for this.
Anyway, hopefully this is something someone will find useful. It's just an example and makes a few assumptions about the document structure but is pretty useful in its current form. And, like me, I think it might help a few people that are learning Mongo and their C# driver while also using JSON.Net to wrap the incoming REST requests.
public BsonDocument ParseUpdateRequest(JObject req)
{
BsonDocument bson = new BsonDocument();
Parse(req, ref bson);
BsonDocument parsedBson = new BsonDocument();
parsedBson["$set"] = bson;
return parsedBson;
}
private void Parse(JObject req, ref BsonDocument bson)
{
/**
* Could use a parent key/node in each recursion call or just use the JToken path
* string.IsNullOrEmpty(parentNode) ? field.Key : parentNode + "." + field.Key;
**/
string key;
JToken val;
foreach (var field in req)
{
key = field.Value.Path;
val = field.Value;
switch (val.Type)
{
case JTokenType.String:
bson.Add(key, (string)val);
break;
case JTokenType.Integer:
bson.Add(key, (int)val);
break;
case JTokenType.Float:
bson.Add(key, (float)val);
break;
case JTokenType.Date:
DateTime dt = (DateTime)val;
bson.Add(key, dt.ToUniversalTime());
break;
case JTokenType.Array:
BsonArray bsonArray = ParseArray((JArray)val);
bson.Add(key, bsonArray);
break;
case JTokenType.Object:
Parse((JObject)val, ref bson);
break;
}
}
return;
}
private BsonArray ParseArray(JArray source)
{
BsonArray bson = new BsonArray();
foreach (JToken field in source)
{
switch (field.Type)
{
case JTokenType.String:
bson.Add((string)field);
break;
case JTokenType.Date:
DateTime dt = (DateTime)field;
bson.Add(dt.ToUniversalTime());
break;
case JTokenType.Integer:
bson.Add((int)field);
break;
case JTokenType.Float:
bson.Add((float)field);
break;
case JTokenType.Object:
BsonDocument nestedDoc = new BsonDocument();
Parse((JObject)field, ref nestedDoc);
bson.Add(nestedDoc);
break;
}
}
return bson;
}
And here's some simple test code I wrote:
ModelUser user = new ModelUser();
ControllerApp app = new ControllerApp();
ControllerApp.Instance.User = user;
JObject req = new JObject();
req["first"] = "First";
req["last"] = "Last";
req["usertype"] = "parent";
req["pw"] = "q345n3452345n2345";
req["array"] = JArray.Parse("[ '1', '2', '3' ]");
req["dateTest"] = DateTime.UtcNow;
req["profile"] = new JObject();
req["profile"]["name"] = new JObject();
req["profile"]["name"]["first"] = "testUpdateFirst";
BsonDocument bd;
bd = user.ParseUpdateRequest(req);
string s = bd.ToJson();