Formatting Serialized JSON With Code-First Entity Framework - c#

I'm using a Web-API GET to return JSON for a Report.
The GET method returns a simple db.Reports.ToList();
This is the dump of the data I retrieve
{
"Project": {
"Location": {
"LocationId": 7,
"Description": "New York"
},
"Department": {
"DepartmentId": 7,
"Description": "Engineering"
},
"ProjectId": 7,
"Description": "Project_3",
"LocationId": 7,
"DepartmentId": 7
},
"Person": {
"Email": "email#gmail.com",
"FirstName": "John",
"LastName": "Doe",
"IsActive": true
},
"StatusCode": {
"StatusId": 8,
"Description": "Accepted"
},
"ReportId": "d4cddb3f-ea6a-4b0a-9820-19bd8ee43b3a",
"Description": "Report 3",
"RoundTrip": 45.88,
"IsBillable": true,
"StartDate": "2013-06-27T00:00:00",
"EndDate": "2013-06-27T14:36:32.467",
"TimeUpdated": "AAAAAAAAJxM="
}, ...
}
This is the related Report declaration:
public class Report
{
public Guid ReportId { get; set; }
public string Description { get; set; }
public double RoundTrip { get; set; }
public bool IsBillable { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public virtual Project Project { get; set; }
public byte[] TimeUpdated { get; set; }
public virtual Person Person { get; set; }
public virtual StatusCode StatusCode { get; set; }
}
In this situation, I'd really like to just have the Ids of the various objects contained in the Report class. For example, I'd really just like to see:
"Project": 7,
"Location": 7,
"Department": 7,
"Person": "email#gmail.com",
"StatusCode": 8,
"ReportId": "d4cddb3f-ea6a-4b0a-9820-19bd8ee43b3a",
"Description": "Report 3",
"RoundTrip": 45.88,
"IsBillable": true,
"StartDate": "2013-06-27T00:00:00",
"EndDate": "2013-06-27T14:36:32.467",
"TimeUpdated": "AAAAAAAAJxM="
Is there a relatively easy way to go about doing this, or would it be in my better interests to just further parse the result I'm seeing already?
Why does EF by default create these objects within the JSON rather than just the foreign keys?

You can do without specifically creating a new class. In your ApiController, if you are using the typed return type (in favor of an HttpResponseMessage), change the List type to IEnumerable<object> and return:
return db.Reports.Select(r => new {
Project = r.ProjectId;
Location = r.Location.LocationId;
Department = r.Department.DepartmentId;
Person = r.Person.Email;
StatusCode = r.StatusCode.StatusId;
Description: r.Description
RoundTrip: r.RoundTrip
IsBillable: r.IsBillable,
StartDate: r.StartDate,
EndDate: r.EndDate
TimeUpdated: r.TimeUpdated
});
// Or if you're using HttpResponseMessage
return Request.CreateResponse(HttpStatusCode.Ok,
db.Reports.Select(r => new {
Project = r.ProjectId;
Location = r.Location.LocationId;
Department = r.Department.DepartmentId;
Person = r.Person.Email;
StatusCode = r.StatusCode.StatusId;
Description: r.Description
RoundTrip: r.RoundTrip
IsBillable: r.IsBillable,
StartDate: r.StartDate,
EndDate: r.EndDate
TimeUpdated: r.TimeUpdated
}));
The default Json serializer (Newtonsoft's Json.Net) is smart enough to serialize anonymous object. The only unknown in the code above is the behaviour of the TimeUpdated member as it's a byte array. You may have to adjust the assignment.

I would recommend making a model for displaying the JSON as you want it to be displayed. This would be the easiest option.
Something like this should work:
public class ReportSimple
{
public Guid ReportId { get; set; }
public int Project { get; set; }
public int Location { get; set; }
public int Department { get; set; }
public string Person { get; set; }
public int StatusCode { get; set; }
public string Description { get; set; }
public double RoundTrip { get; set; }
public bool IsBillable { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public byte[] TimeUpdated { get; set; }
public ReportSimple(Project project, Person person, StatusCode statusCode)
{
Project = project.ProjectId;
Location = project.Location.LocationId;
Department = project.Department.DepartmentId;
Person = person.Email;
StatusCode = statusCode.StatusId;
}
}

Related

How to deserialize json inside a json to a string property

I am reading a json-string from an API (in a script component i SSIS). The json looks something like the one below (this is only one record, the real string contains many more). When trying to deserialize into a class containing the needed properties, I would like to put the "value" for the "costCenters"-property into a string property in my table. How ever, since the costCenters-value in itself contains a JSON, the deserialization fails (because it encounters the objects inside it).
If I exclude the property CostCenters from my class, it manages to deserialize the other properties just fine. I would think (hope) that it would be possible to force the inner JSON into a string property? Any suggestions?
This is my class that is used for the deserilazing:
internal class Unit
{
public int ParentId { get; set; }
public int CompanyId { get; set; }
public string Abbreviation { get; set; }
public string AbbreviationPath { get; set; }
public int Manager { get; set; }
public int UnitId { get; set; }
public string Name { get; set; }
public string LevelDescription { get; set; }
public int OrfuCompanyId { get; set; }
public string Resh { get; set; }
//If the below propery is commented out, the deserializing works fine.
public string CostCenters { get; set; }
public int Level { get; set; }
public int OrfuUnitId { get; set; }
}
This is how I call the deserializer for NewtonSoft:
var units = new List<Unit>();
units = JsonConvert.DeserializeObject<List<Unit>>(jsonString);
This is how the jsonString looks (edited):
[
{
"$id": "1",
"parentId": 999,
"companyId": 9123,
"abbreviation": "ZZZ",
"abbreviationPath": "SOMEPATH",
"costCenters": [
{
"$id": "12",
"costCenter": "12345",
"costCenterSourceId": "99",
"costCenterSource": "TBF",
"costCenterTypeId": "999",
"costCenterType": "TypeOfCostCenter",
"startDate": "2018-01-01T00:00:00",
"endDate": "9999-12-31T00:00:00"
},
{
"$id": "88",
"costCenter": "191945444",
"costCenterSourceId": "88",
"costCenterSource": "TBB",
"costCenterTypeId": "15",
"costCenterType": "SomeTextHere",
"startDate": null,
"endDate": null
}
],
"manager": 12345678,
"deputy": 0,
"homeShare": "\\\\someaddress.net\\someFolder\\SomeCode",
"objectGuid": "ThisIsAGUID",
"distinguishedName": "OU=ABC,OU=NNN,OU=FFF,OU=HHH,OU=HNV,OU=IDK,DC=heipaadeg,DC=com",
"orfuUnitId": 9125,
"orfuCompanyId": 9123,
"resh": "123456789",
"nis": "",
"unitId": 4321,
"name": "2 some name",
"level": 9,
"levelDescription": "Level number 4"
}
]
One workaround is to add a field to Unit called CostCentersString in which the CostCenters list is re-serialized:
In Unit class definition:
...
public List<dynamic> CostCenters { get; set; }
public String CostCentersString { get; set; }
Then use:
List<Unit> units = JsonConvert.DeserializeObject<List<Unit>>(jsonString);
foreach (Unit u in units)
{
u.CostCentersString = JsonConvert.SerializeObject(u.CostCenters);
}

EF Core stop recursion on theninclude

I am using .NET Core 3 with the latest Entity Framework Core. I currently have 3 tables, two normal tables and one linking table. They are structured below. I am trying to get the accessory by itself for the vehicle it is linked to, what currently is happening is that it recurses back into itself and loads the vehicle object again (since it has a reference to the linking table). Does anyone know how I can stop this recursion from taking place? I don't want the VehicleAccessory to have the vehicleAccessories array within it, that is causing the recursion.
Call
var result = _context.Vehicles
.Include(x => x.VehicleAccessories)
.ThenInclude(x => x.Accessory)
.Include(x => x.VehicleImages)
.ThenInclude(x => x.Image)
.ToList();
return result;
Call result
{
"id": 1,
"registrationNumber": "123456",
"make": "BMW",
"model": "M3",
"year": 2009,
"kilometers": 10030,
"vehicleIdentificationNumber": "1234567890",
"retailPrice": 100000.00,
"costPrice": 50000.00,
"vehicleAccessories": [
{
"vehicleId": 1,
"accessoryId": 1,
"accessory": {
"id": 1,
"description": "NEW ONE",
"vehicleAccessories": []
}
},
{
"vehicleId": 1,
"accessoryId": 2,
"accessory": {
"id": 2,
"description": "NEW ONE",
"vehicleAccessories": [
{
"vehicleId": 2,
"vehicle": {
"id": 2,
"registrationNumber": "123456",
"make": "BMW",
"model": "M3",
"year": 2009,
"kilometers": 10030,
"vehicleIdentificationNumber": "1234567890",
"retailPrice": 100000.00,
"costPrice": 50000.00,
"vehicleAccessories": [],
"vehicleImages": [],
"dtCreated": "2020-02-03T11:21:48.2245986",
"dtUpdated": "2020-02-03T11:21:48.2245554"
},
"accessoryId": 2
}
]
}
}
],
"vehicleImages": [],
"dtCreated": "2020-02-03T11:20:13.8890848",
"dtUpdated": "2020-02-03T11:20:13.8890488"
}
Vehicle table:
public class Vehicle
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string RegistrationNumber { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
public int Kilometers { get; set; }
public string VehicleIdentificationNumber { get; set; }
public decimal RetailPrice { get; set; }
public decimal CostPrice { get; set; }
public ICollection<VehicleAccessory> VehicleAccessories { get; } = new List<VehicleAccessory>();
public ICollection<VehicleImage> VehicleImages { get; set; }
public DateTime DTCreated { get; set; }
public DateTime DTUpdated { get; set; }
}
Accessory Table
public class Accessory
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string Description { get; set; }
public ICollection<VehicleAccessory> VehicleAccessories { get; } = new List<VehicleAccessory>();
}
Linking Table
public class VehicleAccessory
{
public long VehicleId { get; set; }
public Vehicle Vehicle { get; set; }
public long AccessoryId { get; set; }
public Accessory Accessory { get; set; }
}
Relationship in context
builder.Entity<VehicleAccessory>()
.HasKey(t => new { t.AccessoryId, t.VehicleId });

How to access properties in asp.net object coming from Deserialied json string

I have tried to use the DeserializeObject function in c# to convert the string to an object which works fine but the only problem rely on accessing the properties within that object such as job Description. How can I do this
My Json String
{
"results": [
{
"jobId": 39621555,
"employerId": 391063,
"employerName": "Opus Recruitment Solutions Ltd",
"employerProfileId": null,
"employerProfileName": null,
"jobTitle": "iOS Developer",
"locationName": "London",
"minimumSalary": 500,
"maximumSalary": 550,
"currency": "GBP",
"expirationDate": "10/01/2020",
"date": "27/12/2019",
"jobDescription": "iOS Developer £500 - £550I have partnered with a large financial organisation based in Central London who are looking for a iOS Developer to join their application development team for their 2020 project as part of a 6 month contract. You will be collaborating with a group of highly skilled developers to implement the latest features for their well established app. Required skills:<b... ",
"applications": 2,
"jobUrl": "https://www.reed.co.uk/jobs/ios-developer/39621555"
}
],
"ambiguousLocations": [],
"totalResults": 9007
}
Attempted solution:
var json = JsonConvert.DeserializeObject<RootObject>(strtest);
ViewBag.Message = json.jobDescription;
public class Result
{
public int jobId { get; set; }
public int employerId { get; set; }
public string employerName { get; set; }
public object employerProfileId { get; set; }
public object employerProfileName { get; set; }
public string jobTitle { get; set; }
public string locationName { get; set; }
public int? minimumSalary { get; set; }
public int? maximumSalary { get; set; }
public string currency { get; set; }
public string expirationDate { get; set; }
public string date { get; set; }
public string jobDescription { get; set; }
public int applications { get; set; }
public string jobUrl { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
public List<object> ambiguousLocations { get; set; }
public int totalResults { get; set; }
}
just this!
var obj= JsonConvert.DeserializeObject<RootObject>(strtest);
forEach(var item in obj.results ){
var jd=item.jobDescription;
}
if your result string is not a list change it in this way
{
"results":
{
"jobId": 39621555,
"employerId": 391063,
"employerName": "Opus Recruitment Solutions Ltd",
"employerProfileId": null,
"employerProfileName": null,
"jobTitle": "iOS Developer",
"locationName": "London",
"minimumSalary": 500,
"maximumSalary": 550,
"currency": "GBP",
"expirationDate": "10/01/2020",
"date": "27/12/2019",
"jobDescription": "iOS Developer £500 - £550I have partnered with a large financial organisation based in Central London who are looking for a iOS Developer to join their application development team for their 2020 project as part of a 6 month contract. You will be collaborating with a group of highly skilled developers to implement the latest features for their well established app. Required skills:<b... ",
"applications": 2,
"jobUrl": "https://www.reed.co.uk/jobs/ios-developer/39621555"
}
,
"ambiguousLocations": [],
"totalResults": 9007
}
then deserialize it to following object
public class RootObject
{
public Result results { get; set; }
public List<object> ambiguousLocations { get; set; }
public int totalResults { get; set; }
}
and pass it to view
var json = JsonConvert.DeserializeObject<RootObject>(strtest);
ViewBag.Message = json.results.jobDescription;

Extract few values from JSON Array

The problem I am facing is that I am getting 0's for the values I ask for in the JSON.
I recently asked a question here about getting specific values from a JSON array response that come from an API.
Now I have a new JSON response from a different route and in there I want one values and its called EntityId its places in a block of Entity See the code for more details, I would like to grab that from this response and place them in a list or Array because it tells me who submitted the assignment in D2L.
UPDATE- After getting comments from a user I used JSON to C# tool to create the full class with all the values but I still get the values as 0,0,0,0.
Right now I am getting 0,0,0,0 values and not getting the actual values if it's possible I would like to grab the whole block on Entity.
JSON
[
{
"Entity": {
"DisplayName": "FullName",
"EntityId": 123,
"EntityType": "User",
"Active": true
},
"Status": 1,
"Feedback": null,
"Submissions": [
{
"Id": 27,
"SubmittedBy": {
"Identifier": "123",
"DisplayName": "FullName"
},
"SubmissionDate": "2019-08-01T15:25:04.130Z",
"Comment": {
"Text": "",
"Html": ""
},
"Files": [
{
"IsRead": false,
"IsFlagged": false,
"IsDeleted": false,
"FileId": 1245,
"FileName": "1.2.10.png",
"Size": 144407
},
{
"IsRead": false,
"IsFlagged": false,
"IsDeleted": false,
"FileId": 292,
"FileName": "1.3.8.png",
"Size": 127869
}
]
}
],
"CompletionDate": "2019-08-01T15:25:04.130Z"
},
{
"Entity": {
"DisplayName": "FullName",
"EntityId": 123,
"EntityType": "User",
"Active": true
},
"Status": 1,
"Feedback": null,
"Submissions": [
{
"Id": 41,
"SubmittedBy": {
"Identifier": "123",
"DisplayName": "FullName"
},
"SubmissionDate": "2019-08-03T03:31:43.807Z",
"Comment": {
"Text": " \nAlex",
"Html": "<p></p>\n<p>Alex</p>"
},
"Files": [
{
"IsRead": false,
"IsFlagged": false,
"IsDeleted": false,
"FileId": 313,
"FileName": "Capture 1.2.10 Questions.PNG",
"Size": 97722
}
]
}
],
"CompletionDate": "2019-08-03T03:31:43.807Z"
}
]
Classes:
public class Entity
{
public string DisplayName { get; set; }
public int EntityId { get; set; }
public string EntityType { get; set; }
public bool Active { get; set; }
}
public class SubmittedBy
{
public string Identifier { get; set; }
public string DisplayName { get; set; }
}
public class Comment
{
public string Text { get; set; }
public string Html { get; set; }
}
public class File
{
public bool IsRead { get; set; }
public bool IsFlagged { get; set; }
public bool IsDeleted { get; set; }
public int FileId { get; set; }
public string FileName { get; set; }
public int Size { get; set; }
}
public class Submission
{
public int Id { get; set; }
public SubmittedBy SubmittedBy { get; set; }
public DateTime SubmissionDate { get; set; }
public Comment Comment { get; set; }
public IList<File> Files { get; set; }
}
public class Example
{
public Entity Entity { get; set; }
public int Status { get; set; }
public object Feedback { get; set; }
public IList<Submission> Submissions { get; set; }
public DateTime CompletionDate { get; set; }
}
Code:
var request = new RestRequest(string.Format(Link));
request.Method = Method.GET;
authenticator.Authenticate(client, request);
var response = client.Execute(request);
var thisasa = JsonConvert.DeserializeObject<List<Example>>
(response.Content).Select(
o => o.Identifier).ToList();
The Example data model shown in your question already can be used to successfully deserialize the JSON shown. All that's left is to pick out the Entity.EntityId property via a Select:
var thisasa = JsonConvert.DeserializeObject<List<Example>>(response.Content)
.Select(o => o.Entity.EntityId)
.ToList();
Demo fiddle #1 here.
Incidentally, if you only need Entity.EntityId you could simplify your data model as follows:
public class Entity
{
public int EntityId { get; set; }
}
public class Example
{
public Entity Entity { get; set; }
}
Demo fiddle #2 here.
(As an aside, since your Example class corresponds to the documented object Dropbox.EntityDropbox, you might want to rename your type to EntityDropbox for clarity.)

What is the best way to desirialize this string of json?

I was wondering how I could at best deserialize this json string. For doing that I am using Newtonsoft.json as a plugin with Xamarin.
I only need the parts that says "transaction" and the array in it "transactions" in a list.
{
"id": 999,
"transactions": [
{
"order": 1,
"displayName": "01_lgn",
"transaction": {
"id": 7791,
"name": "01_lgn",
"description": null,
"warning": 1,
"poor": 2,
"timeOut": 45,
"tolerated": 3,
"frustrated": 7,
"state": 1,
"includeInThroughputCalculation": true
}
}
{
"order": 2,
"displayName": "02",
"transaction": {
"id": 7793,
"name": "02",
"description": null,
"warning": 1,
"poor": 2,
"timeOut": 45,
"tolerated": 3,
"frustrated": 7,
"state": 1,
"includeInThroughputCalculation": true
}
}
],
"defies": null,
"state": 1,
"reportDisplayName": "testSomething"
}
What I already have tried is to put it in a strongly typed class and then make a list of it.
public class testTransaction
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("state")]
public int State { get; set; }
[JsonProperty("reportDisplayName")]
public string ReportDisplayName { get; set; }
[JsonProperty("transactions")]
public List<testTransactions> testTransactions { get; set; }
}
public class testTransactions
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("description")]
public object Description { get; set; }
[JsonProperty("warning")]
public int Warning { get; set; }
[JsonProperty("poor")]
public int Poor { get; set; }
[JsonProperty("timeOut")]
public int TimeOut { get; set; }
[JsonProperty("tolerated")]
public int Tolerated { get; set; }
[JsonProperty("frustrated")]
public int Frustrated { get; set; }
[JsonProperty("state")]
public int State { get; set; }
[JsonProperty("includeInThroughputCalculation")]
public bool IncludeInThroughputCalculation { get; set; }
}
But when I try to deserialize it in this way the "searchResult" is empty and I see that nothing is added to the list.
var bleh = jsonstring;
JObject parsedketenObject = JObject.Parse(bleh);
IList<JToken> jTokenResults1 = parsedketenObject;
IList<JToken> jTokenResults2 = parsedketenObject ["transactions"].Children ().ToList ();
IList<JToken> jTokenResults3 = parsedketenObject["transactions"][0]["transaction"].Children().ToList();
_Transactions_list = new List<testTransaction>();
foreach (JToken result in jTokenResults2)
{
testTransaction searchResult = JsonConvert.DeserializeObject<testTransaction>(result.ToString());
_Transactions_list.Add(searchResult);
}
Firstly, the JSON seems to be malformed, you are missing comma.
{
"id": 999,
"transactions": [
{
"order": 1,
"displayName": "01_lgn",
"transaction": {
"id": 7791,
"name": "01_lgn",
"description": null,
"warning": 1,
"poor": 2,
"timeOut": 45,
"tolerated": 3,
"frustrated": 7,
"state": 1,
"includeInThroughputCalculation": true
}
}, <-------- HERE
{
"order": 2,
"displayName": "02",
"transaction": {
"id": 7793,
"name": "02",
"description": null,
"warning": 1,
"poor": 2,
"timeOut": 45,
"tolerated": 3,
"frustrated": 7,
"state": 1,
"includeInThroughputCalculation": true
}
}
],
"defies": null,
"state": 1,
"reportDisplayName": "testSomething"
}
Additionally, try these for your POCO instead:
public class TransactionDetails
{
public int id { get; set; }
public string name { get; set; }
public object description { get; set; }
public int warning { get; set; }
public int poor { get; set; }
public int timeOut { get; set; }
public int tolerated { get; set; }
public int frustrated { get; set; }
public int state { get; set; }
public bool includeInThroughputCalculation { get; set; }
}
public class Transaction
{
public int order { get; set; }
public string displayName { get; set; }
public TransactionDetails transaction { get; set; }
}
public class RootObject
{
public int id { get; set; }
public List<Transaction> transactions { get; set; }
public object defies { get; set; }
public int state { get; set; }
public string reportDisplayName { get; set; }
}
Then you can use
var x = JsonConvert.DeserializeObject<RootObject>(blah);
x will contain transactions, which is already a list.
This method is not strongly typed, but it will work:
var jsonString = GetTheJson(); // however you get your json
dynamic jsonObject = JsonConvert.DeserializeObject(jsonString);
foreach (var txn in jsonObject.transactions)
{
Console.WriteLine("{0} {1} {2}", txn.order, txn.displayName, txn.transaction.id);
}
The best way to serialize/deserialize a json string to json object is using Google Gson library. You should create DTO files and use its type to serialize the string.
The documentation can be found here: https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/Gson.html

Categories

Resources