Customize object serialization to Json in c# - c#

I am making an asp.net core web api and i want to return Ok(JsonList) in a specific format
I have a list of the following object:
public class obj
{
string schoolName;
int studentscount;
int teacherscount;
}
that would be serialized by default to:
[{"schoolName":"name_1",
"studentscount" : "5",
"teacherscount" : "2"
},
{"schoolName":"name_2",
"studentscount" : "10",
"teacherscount" : "3"
}]
I want the name property to be the name of the object :
[{
"name_1":{
"studentscount" : "5",
"teacherscount" : "2"
},
"name_2:"{
"studentscount" : "10",
"teacherscount" : "3"
}
}]

you can create a new class and try this
Dictionary<string, Counts> counts = JArray.Parse(json).ToDictionary(j => (string)j["schoolName"], j => new Counts
{
studentscount = (int)j["studentscount"],
teacherscount = (int)j["teacherscount"]
});
json = JsonConvert.SerializeObject(counts, Newtonsoft.Json.Formatting.Indented);
public class Counts
{
public int studentscount { get; set; }
public int teacherscount { get; set; }
}
result
{
"name_1": {
"studentscount": 5,
"teacherscount": 2
},
"name_2": {
"studentscount": 10,
"teacherscount": 3
}
}
but if for some reasons you still need an array
var countsArray = new List<Dictionary<string,Counts>> {counts};
json=JsonConvert.SerializeObject(countsArray,Newtonsoft.Json.Formatting.Indented);
result
[
{
"name_1": {
"studentscount": 5,
"teacherscount": 2
},
"name_2": {
"studentscount": 10,
"teacherscount": 3
}
}
]

Related

Does one array contain any value in the other array Mongodb using c#

{
"objects": [
{
"id": 123,
"tracking_datas": [
{
"id": 1,
"polygons": [1,3]
},
{
"id": 2,
"polygons": [3]
},
{
"id": 3,
"polygons": [1,2]
}
]
}
]
}
I have a json file as above. And there is a model that satisfies this json in my NetCore project. I want to get objects containing polygonIds that I have determined with the help of mongodb. How can I do this with c# mongo db?
For example, I have a reference array requiredPolygons: [1,2] and I want to get the data containing these polygon'ids in the tracking data of the objects in the json. The expected result is as follows.
{
"objects":
[
{
"id": 123,
"tracking_datas":[
{
"id": 1,
"polygons": [1,3]
},
{
"id": 3,
"polygons": [1,2]
}
]
}
]
}
public class Test
{
public ObjectId Id { get; set; }
public IEnumerable<Object> objects { get; set; }
[BsonExtraElements]
public BsonDocument UnmappedFields { get; set; } // I'm not sure why it's required, something wrong with mapping configuration,
// but it's a separate question
}
public class Object
{
public int id { get; set; }
public IEnumerable<TrackingData> tracking_datas { get; set; }
}
public class TrackingData
{
public int id { get; set; }
public IEnumerable<int> polygons { get; set; }
[BsonExtraElements]
public BsonDocument UnmappedFields { get; set; } // I'm not sure why it's required, something wrong with mapping configuration,
// but it's a separate question
}
var json = #"{
""objects"": [
{
""id"": 123,
""tracking_datas"": [
{
""id"": 1,
""polygons"": [1,3]
},
{
""id"": 2,
""polygons"": [3]
},
{
""id"": 3,
""polygons"": [1,2]
}
]
}
]
}";
var client = new MongoClient();
var db = client.GetDatabase("so_test");
var coll = db.GetCollection<BsonDocument>("coll");
coll.InsertOne(BsonDocument.Parse(json));
var ids = new[] { 1, 2 };
var typedColl = db.GetCollection<Test>("coll");
var result = typedColl
.Aggregate()
.Project(p =>
new Test
{
Id = p.Id,
objects = p.objects.Select(o =>
new Object
{
id = o.id,
tracking_datas = o.tracking_datas.Where(t => t.polygons.Any(p=>ids.Contains(p)))
})
}
)
.ToList();
Here you go:
db.collection.find({
"objects.tracking_datas.polygons": {
$in: [
1,
2
]
}
})
https://mongoplayground.net/p/MDlIV3YPkZB

Generate recursive object list in C#

I have class models like below :
public class ABC
{
public string value { get; set; }
public List<ABC> children { get; set; }
}
And structure data like this
Parent Value
1 A
A C
2 B
B D
I would like to recursively build an complex object. I have managed to recursively add Children to children.
How can I return List<ABC> like results below ?
[
{
value: '1',
children: [
{
value: 'A',
children: [
{
value: 'C',
},
],
},
],
},
{
value: '2',
children: [
{
value: 'B',
children: [
{
value: 'D',
},
],
},
],
},
];
This sample output what you expect, with more children.
using System;
using System.Collections.Generic;
using System.Text.Json;
public class Json
{
public class ABC
{
public string value { get; set; }
public List<ABC> children { get; set; }
}
public void Run()
{
var abcs = new List<ABC>();
abcs.Add(new ABC()
{
value = "1",
children = new List<ABC>()
{
new ABC() { value = "A", children = new List<ABC>() {
new ABC() { value = "C" }
}},
new ABC() { value = "F" }
}
});
abcs.Add(new ABC()
{
value = "2",
children = new List<ABC>()
{
new ABC() { value = "B", children = new List<ABC>() {
new ABC() { value = "D" }
}},
new ABC() { value = "G" }
}
});
var ser = JsonSerializer.Serialize(abcs, new JsonSerializerOptions() { WriteIndented = true, DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull });
Console.WriteLine(ser);
}
}

Deserialize JSON file with different keys

I have a json like this:
[
{ "Province1" : [
{ "name" : "city-1" },
{ "name" : "city-2" }
]
},
{ "Province2" : [
{ "name" : "city-1" },
{ "name" : "city-2" }
]
}
]
I want to deserialize it using NewtonsoftJson. I have tried this but the result is null:
public class City {
public string Name { get; set; }
}
var cities = JsonConvert.DeserializeObject<IEnumerable<KeyValuePair<string, List<City>>>(File.ReadAllText(#"jsonPath"));
How should I dersialize it to a class?
After fiddling around with it a bit, I've come up with this structure to deserialize it
class MyDeserializer
{
public static void Deserialize()
{
var json = "[{\"Province1\" : [{\"name\" : \"city-1\" }, {\"name\" : \"city-2\" }] }, {\"Province2\" : [{ \"name\" : \"city-1\" }, { \"name\" : \"city-2\" }] } ]";
var cities = JsonConvert.DeserializeObject<List<Dictionary<string, List<City>>>>(json);
Console.WriteLine(cities[0]["Province1"][0].Name);
}
}
class City
{
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
}
That gives you a dictionary for each province which seems a little unintuitive. But that's how your JSON is structured. If you want to combine all the dictionaries into one, you can do it like this
var cities = JsonConvert.DeserializeObject<List<Dictionary<string, List<City>>>>(json).SelectMany(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value);
Console.WriteLine(cities["Province1"][0].Name);
There is probably a more elegant solution to this, however this will give you a dictionary of province name with an array of city name Dictionary<string,string[]>
var dict = JArray
.Parse(input)
.Cast<JObject>()
.Select(x => x.Properties().First())
.ToDictionary(
x => x.Name,
x => x.Values().Values().Select(x => x.First.ToString()).ToArray());
I think your structure should be like this :
[
{ "Name": "Province1",
"Cities": [
{ "name": "city-1" },
{ "name": "city-2" }
]
},
{ "Name": "Province2",
"Cities": [
{ "name": "city-1" },
{ "name": "city-2" }
]
}
]
And to deserilize it :
namespace ConsoleApp2 {
public class Province {
public string Name { get; set; }
public List<City> Cities { get; set; }
}
public class City {
public string Name { get; set; }
}
public class ConsoleApp2 {
public static void Main(string[] args) {
List<Province> provinces = JsonConvert.DeserializeObject<List<Province>>(File.ReadAllText("province.json"));
}
}
}

how to generate json string with an integer as key?

I want to generate json string like this in C# language
{
"error": "0",
"message": "messages",
"data": {
"version": "sring",
"1": [
{
"keyword": "",
"title": ""
},
{
"keyword": "",
"title": ""
}
],
"2": [
...
],
"3": [
...
]
}
}
there is a problem here, "1":[{},{}],how to generate this part? I'm using asp.net mvc project by the way, I want to return this json string to the client web browser.
This response can be simply generated using Dictionary<string, object> with arrays as values.
public class KeywordTitle
{
public string keyword { get; set; }
public string title { get; set; }
}
public class Response
{
public string error { get; set; }
public string message { get; set; }
public Dictionary<string, object> data { get; set; }
}
var dictionary = new Dictionary<string, object> {
{"version", "sring"}
};
dictionary.Add("1", new []
{
new KeywordTitle { keyword = "", title = "" },
new KeywordTitle { keyword = "", title = "" },
new KeywordTitle { keyword = "", title = "" }
});
JsonConvert.SerializeObject(new Response
{
error = "0",
message = "messages",
data = dictionary
});
It generates:
{
"error" : "0",
"message" : "messages",
"data" : {
"version" : "sring",
"1" : [{
"keyword" : "",
"title" : ""
}, {
"keyword" : "",
"title" : ""
}, {
"keyword" : "",
"title" : ""
}
]
}
}
If it is your API, then it is a good idea to extract version in order to make all objects in data be of the same type, and keys of type int.
Get the Json.NET from NuGet. Then, in your MVC model use this data annotation on your Array property
[JsonProperty(PropertyName="1")]
public string[] YourProperty { get; set }
The PropertyName value is used when you serialize data to JSON.
If you are using Newtonsoft.Json NuGet package, serializing a Dictionary<int, List<MyClass>> will get you what you the expected result.
Use Json.net and add the following attribute to the properties you what to modify the name of:
[JsonProperty(PropertyName = "1")]
public List<ObjectName> Objects { get; set; }
For more information have a look at the serialization attributes.

Deserialize Json to Class that implements Ienumerable in Asp.net

I've below function which fetches facebook data and return it as string.
public static string GetUserNewsFeed(string strAccessToken)
{
Dictionary<string, object> PostDetail = new Dictionary<string, object>();
DateTime CreatedDateTime = DateTime.Today.AddDays(-90);
var epoch = (CreatedDateTime.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
PostDetail.Add("Posts", "SELECT post_id,source_id FROM stream WHERE filter_key in (SELECT filter_key FROM stream_filter WHERE uid=me() AND type='newsfeed') and (likes.count > 0 or comments.count > 0) and created_time > " + epoch);
PostDetail.Add("PostComments", "select post_id,fromid from comment where post_id in (select post_id from #Posts)");
PostDetail.Add("PostLikes", "SELECT object_id,post_id,user_id FROM like WHERE post_id in (select post_id from #Posts)");
string Json = HttpUtility.UrlEncode(Newtonsoft.Json.JsonConvert.SerializeObject(PostDetail));
return RunFQLQuery(Json, strAccessToken);
}
Here's the code that calls this function and convert it to Jobject using Json.NET :
strFeed = FacebookAPI.GetUserNewsFeed(Convert.ToString(Session["access_token"]));
JObject objStreamData = JObject.Parse(strFeed);
var PostResponse = objStreamData.SelectToken("data[0]");
Below line deserialize it to NewsFeedPost Class :
var Posts = JsonConvert.DeserializeObject<NewsFeedPost>(PostResponse.ToString());
And below is the class :
public class NewsFeedPost
{
public string name { get; set; }
public List<Post> fql_result_set { get; set; }
}
public class Post
{
public string post_id { get; set; }
public string source_id { get; set; }
}
Now problem is when I change my NewsFeedPost class to below it throws error "Cannot deserialize JSON object into type 'BAL.NewsFeedPost'" :
public class NewsFeedPost : IEnumerable<Post>
{
public string name { get; set; }
public List<Post> fql_result_set { get; set; }
public IEnumerator<Post> GetEnumerator()
{
foreach (Post item in fql_result_set)
{
yield return item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Below is the sample of Json Response :
{
"data": [
{
"name": "Posts",
"fql_result_set": [
{
"post_id": "1"
},
{
"post_id": "2"
}
]
},
{
"name": "PostComments",
"fql_result_set": [
{
"post_id": "3",
"fromid": 4
},
{
"post_id": "5",
"fromid": 6
}
]
},
{
"name": "PostLikes",
"fql_result_set": [
{
"object_id": 7,
"post_id": "8",
"user_id": 9
},
{
"object_id": 10,
"post_id": "11",
"user_id": 12
}
]
}
]
}
I just want to enumerate through list and create comma delimited list and save it to db. Can anybody throw some light what needs to be done? How can I get the Count and Length Property for List?
Two things:
1) Add JsonObjectAttribute to NewsFeedPost:
[JsonObject]
public class NewsFeedPost : IEnumerable<Post>
2) To deserialize that JSON which you show, you need another class:
public class NewsFeedPosts
{
public List<NewsFeedPost> Data { get; set; }
}
and then you'd call your deseralize with that class as what you want deserialized:
var Posts = JsonConvert.DeserializeObject<NewsFeedPosts>(PostResponse.ToString());
You may want to try a cast on the DeserializeObject
var Posts = JsonConvert.DeserializeObject<NewsFeedPost>((NewsFeedPost)PostResponse.ToString());

Categories