I have a task to fetch the list of all missing updates using a C# .NET Framwork 4.7.2 windows Service which runs at specific intervals.
I have gotten this far to Fetch the Missing updates following this Answer.
Now I need to Put all the Fetched data in a JSON file using the following Format:
{
"hostName": "LRD-SomeHost",
"ip" : "192.168.13.12",
"mac" : "MAC:23:23:123:AS"
"timeStamp" : "CURRENT_TIME_STAMP",
"updates" : [
{
"updateID": "b32e464f-2e4a-4109-9018-33583a079a8a",
"updateDetails": [
{
"patchDescription" : "Some Long Description",
"patchCategory" : "28bc880e-0592-4cbf-8f95-c79b17911d5f"
"patchType" : "UpdateClassification"
"patchName" : "Update Rollups"
},
{
"patchDescription" : "Windows 10"
"patchCategory" : "a3c2375d-0c8a-42f9-bce0-28333e198407"
"patchType" : "Product"
"patchName" : "Windows 10"
},
{
"patchDescription" : "Windows 10 LTSB"
"patchCategory" : "d2085b71-5f1f-43a9-880d-ed159016d5c6"
"patchType" : "Product"
"patchName" : "Windows 10 LTSB"
}
]
}
]
}
Following is my C# Model:
namespace UpdateCollector
{
public class Host
{
public string hostname { get; set; }
public string ip { get; set; }
public string mac { get; set; }
public DateTime? timeStamp { get; set; }
public List<Updates> updates { get; set; }
}
public class Updates
{
public string updateID { get; set; }
public List<UpdateDetails> updateDetails { get; set; }
}
public class UpdateDetails
{
public string patchDescription { get; set; }
public string patchCategory { get; set; }
public string patchType { get; set; }
public string patchName { get; set; }
}
}
My Question is How to put my C# Data in this Format?
Thanks
You could use Json.NET to achieve this, here is a possible implementation:
First you need to install the package using NuGet:
Install-Package Newtonsoft.Json -Version 12.0.3
Then you define your classes in the same way you are doing, you can, however, use C# naming conventions and make use of attributes to specify different names for serialization:
public class Host
{
[JsonProperty(PropertyName = "hostname")]
public string Hostname { get; set; }
[JsonProperty(PropertyName = "ip")]
public string Ip { get; set; }
[JsonProperty(PropertyName = "mac")]
public string Mac { get; set; }
[JsonProperty(PropertyName = "timeStamp")]
public DateTime? TimeStamp { get; set; }
[JsonProperty(PropertyName = "updates")]
public List<Updates> Updates { get; set; }
}
public class Updates
{
[JsonProperty(PropertyName = "updateID")]
public string UpdateId { get; set; }
[JsonProperty(PropertyName = "updateDetails")]
public List<UpdateDetails> UpdateDetails { get; set; }
}
public class UpdateDetails
{
[JsonProperty(PropertyName = "patchDescription")]
public string PatchDescription { get; set; }
[JsonProperty(PropertyName = "patchCategory")]
public string PatchCategory { get; set; }
[JsonProperty(PropertyName = "patchType")]
public string PatchType { get; set; }
[JsonProperty(PropertyName = "patchName")]
public string PatchName { get; set; }
}
To serialize your class to json you can use the following statement:
var host = new Host();
// Fill all the properties, lists etc...
string json = JsonConvert.SerializeObject(host, Formatting.Indented);
To deserialize a json string back to the a C# object you use the opposite statement:
Host host = JsonConvert.DeserializeObject<Host>(json);
The code above should work for most cases but if you need to serialize / deserialize any of your objects in a special way you can write a custom JsonConverter: see here for an example.
Install Newtonsoft.Json package and do serialization of your object.
follow below code example.
List<Host> dataList=new List<Host>();
string jsonString = JsonConvert.SerializeObject(dataList);
Related
I am trying to deserialize the following JSON file into 3 variables:
manager(Class)
Servers(list-class)
Admins(List-Class)
Everything I've tried so far doesn't work. How should I do that?
{
"Manager":{
"ServerIp":"ServerIP",
"ServerPort":"6000"
},
"Admins":[
{
"Name":"AdminUserName",
"ID":"AdminID"
}
]
"Servers":[
{
"ServerName":"servername",
"Path":"executablepath",
"IP":"ip",
"Port":"port",
"Password":"pass"
}
]
}
public class Manager
{
public string? ServerIp { get; set; }
public string? ServerPort { get; set; }
}
public class Admins
{
public string? Name { get; set; }
public string? ID { get; set; }
}
public class Servers
{
public string? ServerName { get; set; }
public string? Path { get; set; }
public string? IP { get; set; }
public string? Port { get; set; }
public string? Password { get; set; }
}
Add another class that precisely matches the structure of the JSON that you're describing:
public class Info // come up with a better name than "Info"...
{
public Manager Manager { get; set; }
public List<Admins> Admins { get; set; }
public List<Servers> Servers { get; set; }
}
Then just deserialize the contents of this file into an instance of this class, for example (using System.Text.Json):
var json = File.ReadAllText(pathToFile);
var info = JsonSerializer.Deserialize<Info>(json);
Then just read the properties of info as you need them (Manager, etc.).
here is an equivalent JSON model to your desired C# types. Nullable types are not recommended to use while working with JSON to C# Models.
I don't know if there is an existing name for that case, but I'm trying to retrieve data from NASA API (https://api.nasa.gov/) and I have a simple challenge to catch a list of objects near earth. Here is the JSON response I have from the GET request I do to "https://api.nasa.gov/neo/rest/v1/feed?...."
{
"links": {
"next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-04&end_date=2021-07-04&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-02&end_date=2021-07-02&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-03&end_date=2021-07-03&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"element_count": 6,
"near_earth_objects": {
"2021-07-03": [
{
"links": {
"self": "http://www.neowsapp.com/rest/v1/neo/3701710?api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"id": "3701710",
"neo_reference_id": "3701710",
"name": "(2014 WF497)",
"nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3701710",
"absolute_magnitude_h": 20.23,
"estimated_diameter": {
"kilometers": {
}
And that's the way it is built in Visual Studio (using the Special Paste option for JSON)
public class NearEarthObject
{
public Links links { get; set; }
public int element_count { get; set; }
public Near_Earth_Objects near_earth_objects { get; set; }
}
public class Links
{
public string next { get; set; }
public string prev { get; set; }
public string self { get; set; }
}
public class Near_Earth_Objects
{
public _20210703[] _20210703 { get; set; }
}
public class _20210703
{
public Links1 links { get; set; }
public string id { get; set; }
public string neo_reference_id { get; set; }
public string name { get; set; }
public string nasa_jpl_url { get; set; }
public float absolute_magnitude_h { get; set; }
public Estimated_Diameter estimated_diameter { get; set; }
public bool is_potentially_hazardous_asteroid { get; set; }
public Close_Approach_Data[] close_approach_data { get; set; }
public bool is_sentry_object { get; set; }
}
The question is, inside of the element "near_earth_objects", there is an element called "2021-07-03" (the date of the data I requested), the problem is that I am trying to include it into a DataGridView made in .NET C# (Windows Forms, but that doesn't matters here, I think) and the user wants to get the information by date. So, "2021-07-03" is a valid member just for one day, and the user should be able to get data from multiple days.
So, is there a way in C# to get all child objects inside of near_earth_objects without knowing their names since there will be the option to search for asteroids from date X to Y in my application?
Using System.Text.Json
The API response will map to the following classes
public class Neo
{
public Links Links { get; set; }
public int ElementCount { get; set; }
public Dictionary<string, List<NearEarthObject>> NearEarthObjects { get; set; }
}
public class Links
{
public string Next { get; set; }
public string Prev { get; set; }
public string Self { get; set; }
}
public class NearEarthObject
{
public Links Links { get; set; }
public string Id { get; set; }
public string Name { get; set; }
// Other properties
}
The NearEarthObjects is simply a Dictionary, where the key is the formatted date and value is a List containing NearEarthObject
The PropertyNamingPolicy will allow us to support the API's underscore property naming convention.
public class UnderscoreNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
return name.Underscore();
}
}
Example usage
// using using System.Text.Json;
var response = await new HttpClient().GetStringAsync(url);
var neo = JsonSerializer.Deserialize<Neo>(response, new JsonSerializerOptions
{
PropertyNamingPolicy = new UnderscoreNamingPolicy()
});
foreach(var neos in neo.NearEarthObjects)
{
Console.WriteLine(neos.Key);
}
use System.Text.Json, JsonNamingPolicy
demo code
public class DynamicNamePolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
var today = DateTime.Today.ToString("yyyy-MM-dd");
if (name.Equals("DateData")) //model property name
return today; //convert to json string property name
return name;
}
}
//data deserialize
string data = ""; //json string
var obj = JsonSerializer.Deserialize<NearEarthObject>(data, new JsonSerializerOptions
{
PropertyNamingPolicy = new DynamicNamePolicy(),
});
Im using C# to get a file from my local pc data folder.
This is the code to do that:
var _rootpath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + directory;
var ENC = new Encryption();
var s = File.ReadAllText(_rootpath + "json");
var x = ENC.RijndaelDecrypt(s, App.EncryptionPassword);
This works fine so far.
x got now this value (so this is the string I want to convert to an object) :
{
"items":[
{
"id":194,
"guid":"594394",
"name":"Test",
"connectorId":248,
"customerId":1,
"customerName":"company",
"connectorTypeId":10,
"connectorTypeIcon":null,
"connectorCategoryId":1,
"vendor":"FasterForward",
"isActive":true,
"shopId":null,
"sku":null,
"workerBearerToken":"",
"workerUri":"http://localhost:9000"
}
],
"responseStatus":null
}
After this I want to convert this to an object
var _response = JsonConvert.DeserializeObject<CrmJobListResponse>(x);
This line gives an error:
{"Error converting value x to type 'ServiceModel.CrmJobListResponse'. Path '', line 1, position 991."}
ServiceModel.CrmJobListResponse:
namespace ServiceModel
{
public class CrmJobListResponse : ResponseBase
{
public CrmJobListResponse();
public List<CrmJob> Items { get; set; }
}
}
CrmJob class:
namespace ServiceModel.DTO
{
public class CrmJob : IHasId<int>
{
public CrmJob();
[Ignore]
public string WorkerBearerToken { get; set; }
[PropertyValue("sku")]
public string SKU { get; set; }
[PropertyValue("shop_id")]
public string ShopId { get; set; }
public bool IsActive { get; set; }
public string Vendor { get; set; }
public int ConnectorCategoryId { get; set; }
[Ignore]
public string WorkerRefreshToken { get; set; }
public string ConnectorTypeIcon { get; set; }
public string CustomerName { get; set; }
public int CustomerId { get; set; }
public int ConnectorId { get; set; }
[PropertyValue("jobname")]
public string Name { get; set; }
public string Guid { get; set; }
public int Id { get; set; }
public int ConnectorTypeId { get; set; }
[Ignore]
public string WorkerUri { get; set; }
}
}
Does anyone know why it can't convert my Json string to an object?
I didn't made the code myself, but I don't see why It should go wrong...
If you have a hard time creating DTOs you have some tools that may assist you https://app.quicktype.io/
You can also use paste special in VS to paste a Json directy to a C# class.
This also shows you if you malformed a Json.
I have been trying to get this json to deserialize for two days now using RestSharp. I have gone through the RestSharp github site, looked at countless examples, and spent much time here on Stack Overflow to try and find the answer to no avail. My code had previously worked perfectly but the vendor changed their API version and I was forced to do an update to keep using the application for my legal practice. My json is as follows(client info has been removed and replaced with generic info):
{
"data":[
{
"id":1035117666,
"client":
{
"id":905422394,
"name":"client1"
},
"display_number":"11-00012",
"description":"General",
"practice_area":
{
"id":4269978,
"name":"Business"
},
"status":"Open",
"open_date":"2011-12-14",
"close_date":null,
"billing_method":"hourly"
},
{
"id":1035117768,
"client":
{
"id":905422506,
"name":"client2"
},
"display_number":"12-00037",
"description":"HOA",
"practice_area":
{
"id":4269978,
"name":"Business"
},
"status":"Open",
"open_date":"2012-08-07",
"close_date":null,
"billing_method":"hourly"
}
],
"meta":
{
"paging":
{
"next":"https://app.goclio.com/api/v4/matters.json?fields=id%2C+client%7Bid%2C+name%7D%2C+display_number%2C+description%2C+practice_area%7Bid%2C+name%7D%2C+status%2C+open_date%2C+close_date%2C+billing_method&limit=2&page_token=BAh7BjoLb2Zmc2V0aQc%3D--b1ea3eba20c8acefbcdfc7868debd1e0ee630c64&status=Open"
},
"records":91
}
}
I built the following schema within my c# code:
public class MatterList
{
public List<Matter> matters { get; set; }
public Meta meta { get; set; }
}
public class Meta
{
public Paging paging { get; set; }
public int records { get; set; }
}
public class Paging
{
public string previous { get; set; }
public string next { get; set; }
}
[DeserializeAs(Name = "data")]
public class Matter
{
public int id { get; set; }
public Client client { get; set; }
public string display_number { get; set; }
public string description { get; set; }
public PracticeArea practice_area { get; set; }
public string status { get; set; }
public DateTime open_date { get; set; }
public DateTime close_date { get; set; }
public string billing_method { get; set; }
public string type = "matter";
}
public class PracticeArea
{
public int id { get; set; }
public string name { get; set; }
}
public class Client
{
public int id { get; set; }
public string name { get; set; }
}
When I run the RestSharp deserialize method I am sending the result to an object of type MatterList using the following line of code
MatterList matterList = jsonHandler.Deserialize<MatterList>(response);
I have so far attempted to deserialize without the Meta or Paging POCO classes with the accompanying change to the MatterList class (taking out the Meta property).
I have tried with and without the [DeserializeAs(Name="data")] directive.
I have tried to set the RootElement of the json response prior to deserialization.
I have tried to shorthand the deserialization by combining it with the Execute request code
IRestResponse<MatterList> matterList = client.Execute<MatterList>(request);
I have created a container class called MatterContainer which I placed between MatterList and Matter classes in the schema:
public class MatterList
{
public List<MatterContainer> matters { get; set; }
}
public class MatterContainer
{
public Matter matter { get; set; }
}
public class Matter
{
public int id { get; set; }
public Client client { get; set; }
public string display_number { get; set; }
public string description { get; set; }
public PracticeArea practice_area { get; set; }
public string status { get; set; }
public DateTime open_date { get; set; }
public DateTime close_date { get; set; }
public string billing_method { get; set; }
public string type = "matter";
}
I know I am getting the json response back from the server correctly so my request is proper and MatterList is not null after deserialization. The problem is that I cannot get the deserialization to actually populate the List matters within the MatterList class.
I have been looking at this off and on for two days and cannot get past this hurdle. If anyone sees what I did wrong I would greatly appreciate the insight, I am at a point where I cannot progress further with my application.
Thanks!
I think your [DeserializeAs(Name = "data")] attribute is in the wrong place. Try putting it in the root class instead:
public class MatterList
{
[DeserializeAs(Name = "data")]
public List<Matter> matters { get; set; }
public Meta meta { get; set; }
}
alternatively, try renameing that property to data
Im trying to parse an JSON response string to my class objects.. I can't figure this out and i need some help with this.
I use the json.net reference but i cant't find what i'm looking for :(
my json:
{
"#companyName": "Company Name",
"#version": "1.0",
"#generatedDate": "3/1/10 2:10 PM",
"application": [
{
"#name": "Application #1 name",
"#apiKey": "1234",
"#createdDate": "2010-03-01",
"#platform": "Platform name"
},
{
"#name": "Application #1 name",
"#apiKey": "1234",
"#createdDate": "2010-03-01",
"#platform": "Platform name"
}
]
}
my root class for the json is:
public class RootObject
{
[JsonProperty]
public string companyName { get; set; }
[JsonProperty]
public string version { get; set; }
[JsonProperty]
public string generatedDate { get; set; }
[JsonProperty]
public List<Application> application { get; set; }
}
my sub class (list of applications):
public class Application
{
[JsonProperty]
public string name { get; set; }
[JsonProperty]
public string apiKey { get; set; }
[JsonProperty]
public string createdDate { get; set; }
[JsonProperty]
public string platform { get; set; }
}
To parse it i have the following code now:
JObject obj = JObject.Parse(e.Result);
applications = new RootObject
{
companyName = (string) obj["companyName"],
version = (string) obj["version"],
generatedDate = (string) obj["generatedDate"],
application = ???????? (how to make a list here?)
}
Thanks in advance!
Change your class definitions as follows
public class RootObject
{
[JsonProperty("#companyName")]
public string companyName { get; set; }
[JsonProperty("#version")]
public string version { get; set; }
[JsonProperty("#generatedDate")]
public string generatedDate { get; set; }
public List<Application> application { get; set; }
}
public class Application
{
[JsonProperty("#name")]
public string name { get; set; }
[JsonProperty("#apiKey")]
public string apiKey { get; set; }
[JsonProperty("#createdDate")]
public string createdDate { get; set; }
[JsonProperty("#platform")]
public string platform { get; set; }
}
and deserialize
var rootObj = JsonConvert.DeserializeObject<RootObject>(myjson);
A project I work on occasionally uses Json.Net. It's a wonderful library.
I would use the JsonConvert.DeserializeObject method instead.
In your case I would try something like this:
var result = JsonConvert.DeserializeObject<RootObject>(yourJsonString);
That should take care of it.
Can you try the following code and report back any issues:
RootObject applications = JsonConvert.DeserializeObject<RootObject>(e.Result);