Entity Framework Core self referencing entity JSON response - c#

I have a .Net Core 3.0 Web API project and I'm using Entity Framework as my ORM. I have a self referencing entity that looks like this:
public partial class Category
{
public Category()
{
Events = new HashSet<Event>();
InverseParentCategory = new HashSet<Category>();
}
public int Id { get; set; }
public string Name { get; set; }
public int? ParentCategoryId { get; set; }
public virtual Category ParentCategory { get; set; }
public virtual ICollection<Event> Events { get; set; }
public virtual ICollection<Category> InverseParentCategory { get; set; }
}
And this is the action method in my CategoriesController that returns all the categories as a JSON object:
[HttpGet]
public async Task<IActionResult> GetAllCategories()
{
var allCategories = await _categoryService.GetCategories();
return Ok(allCategories);
}
And this is my GetCategories method in my CategoryService:
public async Task<IEnumerable<Category>> GetCategories()
{
var allCategories = await _context.Categories.ToListAsync();
return allCategories;
}
The response that I get through Postman is this:
[
{
"id": 1,
"name": "Soccer",
"parentCategoryId": null,
"parentCategory": null,
"events": [],
"inverseParentCategory": [
{
"id": 3,
"name": "Basketbal",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 4,
"name": "Volleyball",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 5,
"name": "",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 6,
"name": "dada",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
}
]
},
{
"id": 2,
"name": "Basketbal",
"parentCategoryId": null,
"parentCategory": null,
"events": [],
"inverseParentCategory": []
},
{
"id": 3,
"name": "Basketbal",
"parentCategoryId": 1,
"parentCategory": {
"id": 1,
"name": "Soccer",
"parentCategoryId": null,
"parentCategory": null,
"events": [],
"inverseParentCategory": [
{
"id": 4,
"name": "Volleyball",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 5,
"name": "",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 6,
"name": "dada",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
}
]
},
"events": [],
"inverseParentCategory": []
},
{
"id": 4,
"name": "Volleyball",
"parentCategoryId": 1,
"parentCategory": {
"id": 1,
"name": "Soccer",
"parentCategoryId": null,
"parentCategory": null,
"events": [],
"inverseParentCategory": [
{
"id": 3,
"name": "Basketbal",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 5,
"name": "",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 6,
"name": "dada",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
}
]
},
"events": [],
"inverseParentCategory": []
},
{
"id": 5,
"name": "",
"parentCategoryId": 1,
"parentCategory": {
"id": 1,
"name": "Soccer",
"parentCategoryId": null,
"parentCategory": null,
"events": [],
"inverseParentCategory": [
{
"id": 3,
"name": "Basketbal",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 4,
"name": "Volleyball",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 6,
"name": "dada",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
}
]
},
"events": [],
"inverseParentCategory": []
},
{
"id": 6,
"name": "dada",
"parentCategoryId": 1,
"parentCategory": {
"id": 1,
"name": "Soccer",
"parentCategoryId": null,
"parentCategory": null,
"events": [],
"inverseParentCategory": [
{
"id": 3,
"name": "Basketbal",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 4,
"name": "Volleyball",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
},
{
"id": 5,
"name": "",
"parentCategoryId": 1,
"events": [],
"inverseParentCategory": []
}
]
},
"events": [],
"inverseParentCategory": []
}
]
So you can see that when a child has a parent it return the parent's data and its children. I want to avoid this but I can't actually think of anything. Can I get any help?

Related

Get exception while deserializing JSON

I'm having a problem deserializing a JSON file to an object, it's returning a JSON exception, here's my code:
class Program
{
static void Main(string[] args)
{
LoadJson(filePath);
}
public static void LoadJson(string filePath)
{
using (StreamReader r = new StreamReader(filePath))
{
string json = r.ReadToEnd();
List<Rootobject> items = JsonConvert.DeserializeObject<List<Rootobject>>(json);
}
}
}
public class Rootobject
{
public int total { get; set; }
public Value[] values { get; set; }
}
public class Value
{
public string name { get; set; }
public int count { get; set; }
public int previous_count { get; set; }
}
Here's the JSON file:
{
"total": 520738,
"values": [
{
"name": "2",
"count": 311326,
"previous_count": 11224
},
{
"name": "3",
"count": 73749,
"previous_count": 2747
},
{
"name": "4",
"count": 47810,
"previous_count": 1830
},
{
"name": "6",
"count": 20414,
"previous_count": 759
},
{
"name": "5",
"count": 14481,
"previous_count": 596
},
{
"name": "8",
"count": 7258,
"previous_count": 233
},
{
"name": "7",
"count": 6452,
"previous_count": 286
},
{
"name": "9",
"count": 4439,
"previous_count": 167
},
{
"name": "10",
"count": 4273,
"previous_count": 145
},
{
"name": "12",
"count": 2969,
"previous_count": 82
},
{
"name": "11",
"count": 1890,
"previous_count": 65
},
{
"name": "15",
"count": 1279,
"previous_count": 69
},
{
"name": "16",
"count": 1109,
"previous_count": 36
},
{
"name": "1",
"count": 1021,
"previous_count": 448
},
{
"name": "20",
"count": 906,
"previous_count": 68
},
{
"name": "18",
"count": 867,
"previous_count": 14
},
{
"name": "14",
"count": 844,
"previous_count": 58
},
{
"name": "13",
"count": 380,
"previous_count": 47
},
{
"name": "30",
"count": 376,
"previous_count": 9
},
{
"name": "40",
"count": 296,
"previous_count": 8
},
{
"name": "25",
"count": 282,
"previous_count": 2
},
{
"name": "17",
"count": 224,
"previous_count": 14
},
{
"name": "24",
"count": 188,
"previous_count": 23
},
{
"name": "23",
"count": 165,
"previous_count": 1
},
{
"name": "32",
"count": 157,
"previous_count": 0
},
{
"name": "28",
"count": 71,
"previous_count": 8
},
{
"name": "60",
"count": 48,
"previous_count": 2
},
{
"name": "39",
"count": 39,
"previous_count": 2
},
{
"name": "46",
"count": 29,
"previous_count": 0
},
{
"name": "22",
"count": 27,
"previous_count": 5
},
{
"name": "90",
"count": 24,
"previous_count": 0
},
{
"name": "21",
"count": 23,
"previous_count": 11
},
{
"name": "19",
"count": 20,
"previous_count": 0
},
{
"name": "26",
"count": 17,
"previous_count": 1
},
{
"name": "41",
"count": 16,
"previous_count": 0
},
{
"name": "33",
"count": 13,
"previous_count": 0
},
{
"name": "34",
"count": 10,
"previous_count": 4
},
{
"name": "35",
"count": 10,
"previous_count": 0
},
{
"name": "27",
"count": 9,
"previous_count": 4
},
{
"name": "43",
"count": 8,
"previous_count": 0
},
{
"name": "38",
"count": 8,
"previous_count": 0
},
{
"name": "81",
"count": 7,
"previous_count": 0
},
{
"name": "61",
"count": 6,
"previous_count": 0
},
{
"name": "76",
"count": 3,
"previous_count": 0
},
{
"name": "48",
"count": 3,
"previous_count": 3
},
{
"name": "140",
"count": 2,
"previous_count": 2
},
{
"name": "51",
"count": 2,
"previous_count": 0
},
{
"name": "55",
"count": 2,
"previous_count": 0
},
{
"name": "162",
"count": 1,
"previous_count": 0
},
{
"name": "120",
"count": 1,
"previous_count": 0
},
{
"name": "170",
"count": 1,
"previous_count": 1
},
{
"name": "145",
"count": 1,
"previous_count": 0
},
{
"name": "160",
"count": 1,
"previous_count": 0
},
{
"name": "29",
"count": 1,
"previous_count": 3
},
{
"name": "104",
"count": 1,
"previous_count": 0
},
{
"name": "235",
"count": 1,
"previous_count": 0
},
{
"name": "110",
"count": 1,
"previous_count": 0
},
{
"name": "42",
"count": 1,
"previous_count": 15
},
{
"name": "245",
"count": 1,
"previous_count": 0
},
{
"name": "275",
"count": 1,
"previous_count": 0
},
{
"name": "288",
"count": 1,
"previous_count": 0
},
{
"name": "Other",
"count": 17173,
"previous_count": 934
}
]
}
Tried changing the Value class to a List but still had the same issue. This is the returned exception:
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'total', line 2, position 12.
Thanks!
Your attached JSON is an object with Rootobject type, but not an array.
Deserialize as Rootobject.
Rootobject item = JsonConvert.DeserializeObject<Rootobject>(json);
While in naming conventions, we recommend using Pascal Casing for public members.
Modify all your properties to Pascal Case and apply the [JsonProperty] attribute to map the name of properties in JSON.
With [JsonProperty] attribute
public class Rootobject
{
[JsonProperty("total")]
public int Total { get; set; }
[JsonProperty("values")]
public Value[] Values { get; set; }
}
public class Value
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("count")]
public int Count { get; set; }
[JsonProperty("previous_count")]
public int PreviousCount { get; set; }
}
Or With CamelCasePropertyNamesContractResolver
Rootobject item = JsonConvert.DeserializeObject<Rootobject>(json, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
Demo # .NET Fiddle

Need to get array of values from JSON data

I have the following JSON that is returned to me from an API call. I’m trying to just get the information from a property called “products”. Once I have that into an array or list I need to look for a specific product name and then one of it’s properties.
I’ve tried a handful of different things without any luck. I’m also searching and not finding what I’m looking for in my scenario.
If I use the following, I can get the data into parseJson object but from there I don’t understand how I can pull just the “products” into an array so I can loop through them looking for a specific product and it’s value.
dynamic parseJson = JsonConvert.DeserializeObject(response.Content);
I also tried this but had no luck either.
dynamic parseJson = JsonConvert.DeserializeObject<AccurateApiResult>(response.Content);
public class AccurateApiResult
{
public List<AccurateProduct> products { get; set; }
}
public class AccurateProduct
{
public int id { get; set; }
public string productType { get; set; }
public string status { get; set; }
public string result { get; set; }
public bool flag { get; set; }
}
Here is the sample data and I’m only interested in the “products” section. How can I pull just that data?
[
{
"resource": "ORDER",
"id": "Y10046727",
"created": "2022-06-28T13:18:17Z",
"updated": "2022-06-28T13:18:17Z",
"workflow": "INTERACTIVE",
"candidate": {
"firstName": "Marcus",
"lastName": "Willis",
"middleName": null,
"suffix": null,
"dateOfBirth": "1990-01-01",
"ssn": "111111111",
"email": null,
"phone": "240-5798551",
"address": "3433 Lumar dr",
"city": "Fort Washington",
"region": "MD",
"country": "US",
"postalCode": "20744",
"governmentId": {
"country": "US",
"type": null,
"number": null
},
"aliases": [],
"educations": [
{
"school": "Test University",
"country": "US",
"region": "CA",
"city": "Irvine",
"degree": null,
"major": null,
"startDate": null,
"endDate": null,
"graduated": false,
"graduationDate": null,
"presentlyEnrolled": false
}
],
"prevEmployed": null,
"employments": [],
"convicted": null,
"convictions": null,
"references": [],
"addressHistory": []
},
"completed": "2022-07-07T01:59:13Z",
"supportReferenceId": "Y10046727",
"status": "COMPLETE",
"result": "Meets Requirements",
"products": [
{
"id": 66134505,
"productType": "AELS",
"status": "COMPLETE",
"result": "NOT APPLICABLE",
"flag": false
},
{
"id": 66134506,
"productType": "ADJ",
"status": "COMPLETE",
"result": "NOT APPLICABLE",
"flag": false
},
{
"id": 66134508,
"productType": "MOV",
"status": "COMPLETE",
"result": "Invalid SSN",
"flag": false
},
{
"id": 66144583,
"productType": "MVR",
"status": "COMPLETE",
"result": "NOT APPLICABLE",
"flag": false
},
{
"id": 66144584,
"productType": "F/M",
"status": "COMPLETE",
"result": "NO RECORD FOUND",
"flag": false
},
{
"id": 66144587,
"productType": "EDU",
"status": "COMPLETE",
"result": "NOT APPLICABLE",
"flag": false
},
{
"id": 66144588,
"productType": "DL5D",
"status": "COMPLETE",
"result": "Negative",
"flag": false
}
],
"percentageComplete": 0,
"candidateInfoChanged": false,
"searchId": 66134503,
"subjectId": 10121219,
"requestor": "maegan#email.com"
}
you can try this code
var parsedJsonProducts = (JArray) JArray.Parse(response.Content)[0]["products"];
List<AccurateProduct> products = parsedJsonProducts.ToObject<List<AccurateProduct>>();

How to fetch collection of subdocument using mongodb C# driver?

I have following MongoDB document:
{
"_id": {
"$oid": "5fbfa0005c15aaf2eac69ba6"
},
"PostMedia": [
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img1.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img2.jpg",
"Title": null,
"Description": ""
}
]
},
{
"_id": {
"$oid": "5fbfa0485c15aaf2eac69ba7"
},
"PostMedia": [
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img3.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img4.jpg",
"Title": null,
"Description": ""
}
]
}
and I want to fetch all PostMedia to single array using MongoDB C# driver.
Here is the expected result:
[
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img1.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img2.jpg",
"Title": null,
"Description": ""
}, {
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img3.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img4.jpg",
"Title": null,
"Description": ""
}
]
I had tried to use group aggregation function but it returned an array of array.
Result I received:
PostMedia:[{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img1.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img2.jpg",
"Title": null,
"Description": ""
}],[
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img3.jpg",
"Title": null,
"Description": ""
},
{
"FilePath": "http://localhost:8886/localhost44323/image/",
"Filename": "img4.jpg",
"Title": null,
"Description": ""
}
]
C# code I have written so far is as follows:
var group = new[]
{
new BsonDocument("$group",
new BsonDocument
{
{ "_id", BsonNull.Value },
{ "PostMedia", new BsonDocument("$push", "$PostMedia") }
})
};
var result = collection.Aggregate<MediaList>(group).FirstOrDefault();
return list;
}
Is there any way to fetch subdocument by merging them is a single array.
You have to $unwind before $group,
$unwind deconstruct PostMedia array
$replaceRoot replace PostMedia object to root
$unset remove _id field
{ $unwind: "$PostMedia" },
{
$group: {
_id: null,
PostMedia: { $push: "$PostMedia" }
}
},
{ $unset: "_id" } // remove field
Playground
C#:
new BsonArray
{
new BsonDocument("$unwind", "$PostMedia"),
new BsonDocument("$group",
new BsonDocument
{
{ "_id", BsonNull.Value },
{ "PostMedia",
new BsonDocument("$push", "$PostMedia") }
})
new BsonDocument("$unset", "_id")
}

how to convert a JSON structure to another and add a extra field in to it

i have json data, which is coming from an API. the structure of json is like this
{
"data": [
{
"nameid": "s_10",
"size": "6.46",
"name": "abc",
"children": [
{
"nameid": "i_101010",
"size": "8.84",
"name": "bcd",
"children": [
{
"nameid": "si_10101010",
"size": "4.00",
"name": "efg",
"children": [
{
"nameid": "c_3273",
"size": 4,
"name": "ttt",
}
]
},
{
"nameid": "si_10101020",
"size": "13.67",
"name": "sss",
"children": [
{
"nameid": "c_4450",
"size": 1,
"name": "rrr",
},
{
"nameid": "c_551",
"size": 17,
"name": "ddd",
},
i need to convert it to something like the below structure
{
"id": 1,
"parentId": "NULL",
"name": "Root",
"size": 5,
"children": [
{
"id": 10,
"parentId": "1",
"name": "En",
"size": 1,
"children": [
{
"id": 1010,
"parentId": "10",
"name": "Eee",
"size": 1,
"children": [
{
"id": 101010,
"parentId": "1010",
"name": "Enh",
"size": 5,
"children": [
{
"id": 10101010,
"parentId": "101010",
"name": "Ooo",
"size": 5
},
so in short, i need to add that field parent id to the first JSON
note: these are partial data, so json may not be a valid one.
If your source and destination object are Typed Class (e.g. public class FamilyMembers)
Automapper is the best way to achieve this.
http://automapper.org/
Let's say your source 'data" is class Families. You can map Families to FamilyMembers
//specify source, destination
Mapper.CreateMap<Families, FamilyMembers>();
//get source data
Families families = GetFamiliesFromAPI();
//map each properties of families to familymembers
FamilyMembers familymembers = Mapper.Map<Families, FamilyMembers>(families);
ShowFamilyMembersInDataGrid(familymembers);
If you don't want to use Automapper, then go with LINQ
Families families = GetFamiliesFromAPI();
families.Select(f => f, new FamilyMembers() {name = f.Name, someProperty = f.someProperty }
Since you have nested JSON object you need to learn how to handle such as "children" member in your source data and map if via LINQ accordingly

Cannot deserialize JSON object into type 'System.Collections.Generic.List'

i'm trying to deserialize a json string pulled from the web using json.net, but i am getting a Cannot deserialize JSON object error. Here is the json string
{
"metadata": {
"page": 1,
"perPage": 23,
"count": 23
},
"results": [
{
"id": 9,
"name": "Breaks",
"slug": "breaks",
"subgenres": []
},
{
"id": 10,
"name": "Chill Out",
"slug": "chill-out",
"subgenres": []
},
{
"id": 12,
"name": "Deep House",
"slug": "deep-house",
"subgenres": []
},
{
"id": 16,
"name": "DJ Tools",
"slug": "dj-tools",
"subgenres": []
},
{
"id": 1,
"name": "Drum & Bass",
"slug": "drum-and-bass",
"subgenres": []
},
{
"id": 18,
"name": "Dubstep",
"slug": "dubstep",
"subgenres": []
},
{
"id": 17,
"name": "Electro House",
"slug": "electro-house",
"subgenres": []
},
{
"id": 3,
"name": "Electronica",
"slug": "electronica",
"subgenres": []
},
{
"id": 40,
"name": "Funk / R&B",
"slug": "funk-r-and-b",
"subgenres": []
},
{
"id": 49,
"name": "Glitch Hop",
"slug": "glitch-hop",
"subgenres": []
},
{
"id": 8,
"name": "Hard Dance",
"slug": "hard-dance",
"subgenres": []
},
{
"id": 2,
"name": "Hardcore / Hard Techno",
"slug": "hardcore-hard-techno",
"subgenres": []
},
{
"id": 38,
"name": "Hip-Hop",
"slug": "hip-hop",
"subgenres": []
},
{
"id": 5,
"name": "House",
"slug": "house",
"subgenres": []
},
{
"id": 37,
"name": "Indie Dance / Nu Disco",
"slug": "indie-dance-nu-disco",
"subgenres": []
},
{
"id": 14,
"name": "Minimal",
"slug": "minimal",
"subgenres": []
},
{
"id": 39,
"name": "Pop / Rock",
"slug": "pop-rock",
"subgenres": []
},
{
"id": 15,
"name": "Progressive House",
"slug": "progressive-house",
"subgenres": []
},
{
"id": 13,
"name": "Psy-Trance",
"slug": "psy-trance",
"subgenres": []
},
{
"id": 41,
"name": "Reggae / Dub",
"slug": "reggae-dub",
"subgenres": []
},
{
"id": 11,
"name": "Tech House",
"slug": "tech-house",
"subgenres": []
},
{
"id": 6,
"name": "Techno",
"slug": "techno",
"subgenres": []
},
{
"id": 7,
"name": "Trance",
"slug": "trance",
"subgenres": []
}
]
}
And my classes
public class Genres
{
public Metadata metadata { get; set; }
public List<Result> results { get; set; }
}
public class Metadata
{
public int page {get; set; }
public int perPage { get; set;}
public int count { get; set; }
}
public class Result
{
public int id { get; set; }
public string name { get; set; }
public string slug { get; set; }
public List<object> subgenres { get; set; }
}
And my code to deserialize the data using json.net.
void beatportTest_GetDataCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
List<Result> data = JsonConvert.DeserializeObject<List<Result>>(e.Result);
//foreach loop to display data
I want to be able to display the name of each genre from the Results class, but i get the error when my app compiles.
Your JSON data has two main elements metadata and results. And according to you class structure, the Genres class also has the same structure. But in your code you are trying to de-serialize the structure to Results, thats why you are getting the error.You should try to de-serialize to Genres class.The new code will be something like
void beatportTest_GetDataCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
Genres data = JsonConvert.DeserializeObject(e.Result);
// for-each loop to display data
}
catch(Exception ex)
{
}
}

Categories

Resources