MongoDB serializing ObjectId to string - c#

Consider the following piece of code
public string sector_get(string id)
{
var client = new MongoClient(connectionstring);
var db = client.GetDatabase("databasename");
var sectorsColl = db.GetCollection<BsonDocument>("sectors");
try
{
BsonDocument sectorObj = sectorsColl.Find(Builders<BsonDocument>.Filter.Eq<ObjectId>("_id", ObjectId.Parse(id))).FirstOrDefault;
return sectorObj.ToJson();
}
catch (Exception ex)
{
throw;
}
}
The function returns the following :
{
"_id": ObjectId("5eb0f25d70a5a75108a2eb5d"),
"title": "Supermarkets",
"subTitle": "Grocerie made easy",
"image": "images/sector/supermarket.jpg",
"displayOrder": 1,
"flatList": 2
}
I need to serialize the string value of "_id" instead of the ObjectId value (as presented below).
{
"_id": "5eb0f25d70a5a75108a2eb5d",
"title": "Supermarkets",
"subTitle": "Grocerie made easy",
"image": "images/sector/supermarket.jpg",
"displayOrder": 1,
"flatList": 2
}
Please note that creating a class based data model, with attribute serialization decoration is not an option.
Your help is appreciated.

Related

Return multiple objects from an action

I want to fetch data from an Oracle database with Dapper ORM in .NET 6.0.
This is the code to fetch the data:
[HttpGet]
[Route("api/GetDatas")]
public object GetDatas(string? nom = null, string? pre = null)
{
var queryResult = userRepository.GetDatas(nom, pre);
var totalResult = userRepository.GetDatasFullQueryResult(nom, pre);
int timeStamp = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1,1))).TotalSeconds;
if (queryResult == null)
{
return NotFound(Tools.returnError("erreur lors de la récuperation des flux avocats, endpoint: api/GetDatas"));
}
return Ok(queryResult); // here my problem
}
I have result in each variable (queryResult, totalResult, timeStamp) and I want to construct a json response like this:
{
"metadata":
[
{
"totalResult": "2",
"timestamp": "1673347991"
}
],
"fiche_avocats":
[
{
"nom": "doe",
"pre": "john"
}
],
[
{
"nom": "foo",
"pre": "bar"
}
]
}
I tried to use a Tuple native type, but the result is like item1: [1673347991]..
Thanks a lot for helping me!
Thery
you can use this solution :
[HttpGet]
[Route("api/GetDatas")]
public object GetDatas()
{
List<object> listObj = new List<object>();
var queryResult = ....................;
var totalResult = ....................;
int timeStamp =.......................;
listObj.Add(queryResult);
listObj.Add(totalResult);
listObj.Add(timeStamp);
return Json(listObj);
}

Deserialize objects nested within an array [duplicate]

This question already has answers here:
Parse JSON in C#
(7 answers)
Closed 4 years ago.
I am struggling to deserialize the following JSON string that I am receiving from an API:
{
"appointment_types": [
{
"id": 279148,
"max_attendees": 1,
"name": "Follow up",
"billable_item": {
"links": {
"self": "https://api.cliniko.com/v1/billable_items/485545"
}
},
"practitioners": {
"links": {
"self": "https://api.cliniko.com/v1/appointment_types/279148/practitioners"
}
}
},
{
"id": 279149,
"max_attendees": 1,
"name": "Assessment",
"billable_item": {
"links": {
"self": "https://api.cliniko.com/v1/billable_items/490437"
}
},
"practitioners": {
"links": {
"self": "https://api.cliniko.com/v1/appointment_types/279149/practitioners"
}
}
}
],
"total_entries": 17,
"links": {
"self": "https://api.cliniko.com/v1/appointment_types?page=1"
}
}
I have searched but I couldn't find anything that would work for the above.
Any pointers that may get me on the right track would be greatly appreciated.
This seems to work fine for me just using dynamic...
dynamic d = JObject.Parse(json);
var totalNumber = d.total_entries.ToString();
var theId = d.appointment_types[0].id.ToString();
What have you tried?
I would create c# classes for the structure and then use Newtonsoft Json.NET for deserializion. (It is fast and already in c# but you have to add the reference.)
Here is my code:
class Program
{
static void Main(string[] args)
{
string json = File.ReadAllText("demo.json"); //Your json here
RequestResult requestResult = Newtonsoft.Json.JsonConvert.DeserializeObject<RequestResult>(json); //There is your result
Console.WriteLine("Done!");
Console.ReadLine();
}
}
class RequestResult
{
public AppointmentType[] appointment_types;
public int total_entries;
public Link links;
}
class Practitioners
{
public Link links;
}
class BillableItem
{
public Link links;
}
class Link
{
public string self;
}
class AppointmentType
{
public int id;
public int max_attendees;
public string name;
public BillableItem billable_item;
public Practitioners practitioners;
}
Then you have the result as a c# object and things like intellisense and code completion do work.

Deserialize JSON with variable property name and nested list to object

I have a bunch of API which generates the following 2 kinds of reply in response body:
{ "error": null, "object_type": { /* some object */ } }
{ "error": null, "object_type": [{ /* some object */ }, { /* some object */ }, ...] }
While I have a class corresponding to the object structure, I want to deserialize the API endpoints directly into either an object of the class or a List<class>, without creating some "result" classes to match the response JSON structure. Is this possible?
For example there is 2 API:
/api/getAllCompanies
returns
{ "error": null, "company": [ { "name": "Microsoft", "country": "US" }, { "name": "Apple", "country": "US" } ]
while
/api/getUserCompany
returns
{ "error": null, "company": { "name": "Microsoft", "country": "US" } }
I have a class in code:
public class Company {
string Name { get; set; }
string Country { get; set; }
}
How can I directly deserialize the data into a Company object or a List<Company> without creating a bunch of other class?
(The JSON property name (company) is known so don't need to extract it elsewhere.)
I've been trying to first deserialize the response JSON into an ExpandoObject then copy the properties to an instance of destination class using the code here then convert it using the following code, but this seems not to work with lists.
private static async Task<T> GetApiObject<T>(string api, string extractedObjName) where T: class, new()
{
var retstr = await /* get API response as string */;
dynamic retobj = JsonConvert.DeserializeObject<ExpandoObject>(retstr, new ExpandoObjectConverter());
var ret = new T();
Mapper<T>.Map((ExpandoObject)((IDictionary<string, object>)retobj)[extractedObjName], ret);
return ret;
}
You can use JObejct to extract the information you need before deserialize it into the object.
var str = "{ \"error\": null, \"company\": [{ \"name\": \"Microsoft\", \"country\": \"US\" } ,{ \"name\": \"Apple\", \"country\": \"US\" } ]}";
var temp = JObject.Parse(str).GetValue("company");
var companies = temp.Select(x => x.ToObject<Company>()).ToList();
Same goes for /api/getUserCompany
var str = "{ \"error\": null, \"company\": { \"name\": \"Microsoft\", \"country\": \"US\" } }";
var temp = JObject.Parse(str).GetValue("company");
var company = temp.ToObject<Company>();

JSON Get List of attributes values

I have the following JSON, and I want to take a list of IDs with its values
For example in LINQ something like this: result.Select(x=>x.id)
I tried this:
var inner = outer["pictures"].Value<JArray>().ToList();
I have a list there but with all attributes but I am not able to select just IDs since it is an anonymous list.
outer
{{
"id": "669654603",
"pictures": [
{
"id": "659745-MLA25600661898_052017",
"url": "http://mla-s2-p.mlstatic.com/659745-MLA25600661898_052017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/659745-MLA25600661898_052017-O.jpg",
"size": "500x365",
"max_size": "625x457",
"quality": ""
},
{
"id": "908422-MLA25658267858_062017",
"url": "http://mla-s2-p.mlstatic.com/908422-MLA25658267858_062017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/908422-MLA25658267858_062017-O.jpg",
"size": "47x47",
"max_size": "47x47",
"quality": ""
},
{
"id": "794138-MLA25658267889_062017",
"url": "http://mla-s2-p.mlstatic.com/794138-MLA25658267889_062017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/794138-MLA25658267889_062017-O.jpg",
"size": "40x40",
"max_size": "40x40",
"quality": ""
}
]
}}
When working with Newtonsoft JSON you can do it like this:
var values = JObject.Parse(jsonString)["pictures"].Select(p => p["id"].Value<string>()).ToList();
In order to be valid your json should not contain double curly brackets:
{
"id": "669654603",
"pictures": [ ... ]
}
You can parse it without additional classes:
var ids = JObject.Parse(json)["pictures"].Select(p => (string)p["id"]);
Output:
[
"659745-MLA25600661898_052017",
"908422-MLA25658267858_062017",
"794138-MLA25658267889_062017"
]
Or you can create several classes to hold your json data:
public class Container
{
public List<Picture> Pictures { get; set; }
}
public class Picture
{
public string Id { get; set; }
// you can add other properties here
}
And use strongly-typed parsing:
var ids = JsonConvert.DeserializeObject<Container>(json).Pictures.Select(p => p.Id);

Search for a nested value inside of a JSON.net object in C#

I've got a JSON stream coming back from a server, and I need to search for a specific value of the node "ID" using JSON.net to parse the data.
And I can almost make it work, but not quite because the results coming back are deeply nested in each other -- this is due to the fact that I'm getting a folder structure back. I've boiled the JSON down to a much simpler version. I'm getting this:
{
"data": {
"id": 0,
"name": "",
"childFolders": [{
"id": 19002,
"name": "Locker",
"childFolders": [{
"id": 19003,
"name": "Folder1",
"childFolders": [],
"childComponents": [{
"id": 19005,
"name": "route1",
"state": "STOPPED",
"type": "ROUTE"
}]
}, {
"id": 19004,
"name": "Folder2",
"childFolders": [],
"childComponents": [{
"id": 19008,
"name": "comm1",
"state": "STOPPED",
"type": "COMMUNICATION_POINT"
}, {
"id": 19006,
"name": "route2",
"state": "STOPPED",
"type": "ROUTE"
}, {
"id": 19007,
"name": "route3",
"state": "STOPPED",
"type": "ROUTE"
}]
}],
"childComponents": []
}],
"childComponents": []
},
"error": null
}
I can almost get there by going:
var objects = JObject.Parse(results);
var subobjects = objects["data"]["childFolders"][0]["childFolders"][1];
I can see in the debug view that it'll parse the object, but won't let me search within.
My ultimate goal is to be able to search for "route3" and get back 19007, since that's the ID for that route. I've found some results, but all of them assume you know how far nested the object is. The object I'm searching for could be 2 deep or 20 deep.
My ultimate goal is to be able to search for "route3" and get back 19007
You can use linq and Descendants method of JObject to do it:
var dirs = JObject.Parse(json)
.Descendants()
.Where(x=>x is JObject)
.Where(x=>x["id"]!=null && x["name"]!=null)
.Select(x =>new { ID= (int)x["id"], Name = (string)x["name"] })
.ToList();
var id = dirs.Find(x => x.Name == "route3").ID;
You can use the SelectToken or SelectTokens functions to provide a JPath to search for your desired node. Here is an example that would provide you the route based on name:
JObject.Parse(jsonData)["data"].SelectToken("$..childComponents[?(#.name=='route3')]")
You can find more documentation on JPath here
Simply write a recursive function:
private Thing FindThing(Thing thing, string name)
{
if (thing.name == name)
return thing;
foreach (var subThing in thing.childFolders.Concat(thing.childComponents))
{
var foundSub = FindThing(subThing, name);
if (foundSub != null)
return foundSub;
}
return null;
}
class RootObject
{
public Thing data { get; set; }
}
class Thing
{
public int id { get; set; }
public string name { get; set; }
public List<Thing> childFolders { get; set; } = new List<Thing>();
public List<Thing> childComponents { get; set; } = new List<Thing>();
}
And using it:
var obj = JsonConvert.DeserializeObject<RootObject>(jsonString);
var result = FindThing(obj.data, "route3");

Categories

Resources