I got JSON from some process as following:
{
"Nodename": "Host1",
"OperatingSystem": "OS",
"Release": "3.6.2.1",
"Stats": [{
"Timestamp": "11/18/2021 18:31:58",
"Processes": [{
"Timestamp": "11/18/2021 18:31:58",
"Processname": "process1",
"CpuPercent": 0,
"MemoryPercent": 0.16,
}, {
"Timestamp": "11/18/2021 18:31:58",
"Processname": "process2",
"CpuPercent": 0,
"MemoryPercent": 0.46,
}, {
"Timestamp": "11/18/2021 18:31:58",
"Processname": "process3",
"CpuPercent": 0,
"MemoryPercent": 0.69,
}
]
}, {
"Timestamp": "11/18/2021 18:32:08",
"Processes": [{
"Timestamp": "11/18/2021 18:32:08",
"Processname": "process1",
"CpuPercent": 0,
"MemoryPercent": 0.16,
}, {
"Timestamp": "11/18/2021 18:32:09",
"Processname": "process2",
"CpuPercent": 0,
"MemoryPercent": 0.46,
}, {
"Timestamp": "11/18/2021 18:32:09",
"Processname": "process3",
"CpuPercent": 0,
"MemoryPercent": 0.69,
}
]
}, {...}
]}
I need to sum all the values based on process as key in another JSON like
{
"process1": {
"AverageCpu": xxx,
"AverageMemory": yyy,
},
"process2": {
"AverageCpu": xxx,
"AverageMemory": yyy,
},
"process3": {
"AverageCpu": xxx,
"AverageMemory": yyy,
}
}
I am trying with normal foreach with "groupby" but not able to get actual result.
I do not want to iterate many times as this source JSON can be huge.
Thanks
You can use tools such as Json2Csharp to generate the classes based on JSON.
public class Process
{
public string Timestamp { get; set; }
public string Processname { get; set; }
public int CpuPercent { get; set; }
public double MemoryPercent { get; set; }
}
public class Stat
{
public string Timestamp { get; set; }
public List<Process> Processes { get; set; }
}
public class Root
{
public string Nodename { get; set; }
public string OperatingSystem { get; set; }
public string Release { get; set; }
public List<Stat> Stats { get; set; }
}
public class GroupedProcessStat
{
public double AverageCpu {get;set;}
public double AverageMemory {get;set;}
}
Deserialize JSON to Root class via Newtonsoft.Json.JsonConvert.
Retrieve processes via .SelectMany() from System.Linq.
.GroupBy() processName and convert it to dictionary via .ToDictionary().
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
var root = JsonConvert.DeserializeObject<Root>(json);
var processes = root.Stats
.SelectMany(x => x.Processes)
.ToList();
var groupedProcessDict = processes.GroupBy(x => x.Processname)
.ToDictionary(
x => x.Key,
x => new GroupedProcessStat
{
AverageCpu = x.Average(y => y.CpuPercent),
AverageMemory = x.Average(y => y.MemoryPercent)
});
var groupedProcessJson = JsonConvert.SerializeObject(groupedProcessDict);
Console.WriteLine(groupedProcessJson);
Output
{"process1":{"AverageCpu":0.0,"AverageMemory":0.16},"process2":{"AverageCpu":0.0,"AverageMemory":0.46},"process3":{"AverageCpu":0.0,"AverageMemory":0.69}}
Sample Program on .NET Fiddle
Related
I've created two c# classes and then deserialize the Json returned to work with it natively.
class structureTree
{
public structureChildren[] children { get; set; }
}
class structureChildren
{
public structureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
The Data returned is like this
[
{
"children": [
{
"children": [
{
"children": [
{
"children": [],
"myentity": "ENT2_A",
"from": "2019-10-01",
"structureId": 34353,
"to": null
},
{
"children": [
{
"children": [],
"myentity": "ENT3_A",
"from": "2019-10-01",
"structureId": 34349,
"to": null
},
{
"children": [],
"myentity": "ENT3_B",
"from": "2019-10-01",
"structureId": 34351,
"to": null
}
],
"myentity": "ENT2_B",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
],
"myentity": "ENT1_A",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
],
"myentity": "ENT0_A",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
]
}
]
I need to get all "myentity" elements and if it's possible in which level resides.
If not possible obtain level, another way is get all "myentity" for each level.
Probably there are much better and elegant ways of doing this. This is without thinking on it much:
void Main()
{
var st = JsonConvert.DeserializeObject<List<structureTree>>(myjson);
List<Tuple<string,int>> entities = new List<System.Tuple<string, int>>();
foreach (var stc in st)
{
foreach (var sc in stc.children)
{
GetMyEntity(entities, sc, 0);
}
}
foreach (var e in entities)
{
Console.WriteLine($"{e.Item1}, {e.Item2}");
}
}
void GetMyEntity(List<Tuple<string,int>> entities, structureChildren c, int level)
{
entities.Add(Tuple.Create(c.myentity,level));
level++;
foreach (var sc in c.children)
{
GetMyEntity(entities, sc, level);
}
}
class structureTree
{
public structureChildren[] children { get; set; }
}
class structureChildren
{
public structureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
static readonly string myjson = #"[
{
""children"": [
{
""children"": [
{
""children"": [
{
""children"": [],
""myentity"": ""ENT3_A"",
""from"": ""2019-10-01"",
""structureId"": 34353,
""to"": null
},
{
""children"": [
{
""children"": [],
""myentity"": ""ENT3_B"",
""from"": ""2019-10-01"",
""structureId"": 34349,
""to"": null
},
{
""children"": [],
""myentity"": ""ENT3_C"",
""from"": ""2019-10-01"",
""structureId"": 34351,
""to"": null
}
],
""myentity"": ""ENT2_A"",
""from"": ""2019-10-01"",
""structureId"": 34348,
""to"": null
}
],
""myentity"": ""ENT1_1"",
""from"": ""2019-10-01"",
""structureId"": 34348,
""to"": null
}
]
}
]
}
]";
Output:
, 0
ENT1_1, 1
ENT3_A, 2
ENT2_A, 2
ENT3_B, 3
ENT3_C, 3
You can do it in two ways, with a stack/queue or recursion. I personally prefer stacks since recursion is hard(er) to debug. This is a quick draft. I'm sure someone else can give you a fancy recursion version with Linq, but I think this illustrates the steps you need to take better.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var structure = new StructureTree();
var currentStack = new Stack<StructureChildren>(structure.children);
var nextStack = new Stack<StructureChildren>();
var flatStructure = new List<KeyValuePair<int, string>>();
int currentLevel = 0;
bool loop = true;
while (loop)
{
var currentItem = currentStack.Pop();
foreach (var child in currentItem.children)
nextStack.Push(child);
flatStructure.Add(new KeyValuePair<int, string>(currentLevel, currentItem.myentity));
if (currentStack.Count == 0)
{
if (nextStack.Count == 0)
break;
currentLevel++;
currentStack = new Stack<StructureChildren>(nextStack);
nextStack.Clear();
}
}
}
public class StructureTree
{
public StructureChildren[] children { get; set; }
}
public class StructureChildren
{
public StructureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
}
PS: Please look into the naming convention provided by Microsoft. Class names should be CapitalizedAtEveryWord and property names too. Your current naming scheme is typically used for Java, not C#.
I have Json where i have 2 objects. I would like to know how to change value in my json, when other value is looking for. For example i would like to change "speciality" to "Warrior" for Person who's "Name" is Harry.
It's my Json
{
"Person": [
{
"Speciality": "Archer",
"Id": 432742,
"Name": "Charlie",
"Surname": "Evans",
"Items": [
"Bow",
"Arrow",
]
},
{
"Speciality": "Soldier",
"Id": 432534,
"Name": "Harry",
"Surname": "Thomas",
"Items": [
"Gun",
"Knife",
]
}
],
"Monster": [
{
"Name": "Papua",
"Skills": [
"Jump",
"SlowWalk",
]
},
{
"Name": "Geot",
"Skills": [
"Run",
"Push",
]
}
]
}
My classes
public class Person
{
public string Speciality { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public List<string> Items { get; set; }
}
public class Monster
{
public string Name { get; set; }
public List<string> Skills { get; set; }
}
public class Root
{
public List<Person> People { get; set; }
public List<Monster> Monsters { get; set; }
}
I tried something like this:
var result = JsonSerializer.Deserialize<Root>(jsonfile)
for (int i = 0; i < result.People.Count; ++i)
{
result.Where(w => w.Person.Name == "Harry").ToList().ForEach(s => s.Person.Speciality = "Warrior");
}
Thanks in advance for some help.
Your can use foreach loop
var result = JsonSerializer.Deserialize<Root>(jsonfile);
foreach (var person in result.Person)
{
if(person.Name == "Harry"){
person.Speciality = "";
}
}
i'm assigned a task to parse azure alerts and extract relevant information from azure alerts. Is there any nuget package which parses azure alerts and extracts resource group/subscription/resource name and alert details ?
Here is sample alert format
{
"schemaId": "azureMonitorCommonAlertSchema",
"data": {
"essentials": {
"alertId": "/subscriptions/63b6a1c5-3552-4676-8073-c31e2641f787/providers/Microsoft.AlertsManagement/alerts/7cf70adc-c221-467c-bcfe-bab9e33d98b2",
"alertRule": "AlertMetricCPUPercentage",
"severity": "Sev0",
"signalType": "Metric",
"monitorCondition": "Fired",
"monitoringService": "Platform",
"alertTargetIDs": [
"/subscriptions/63b6a1c5-3552-4676-8073-c31e2641f787/resourcegroups/bridge/providers/microsoft.compute/virtualmachines/vm01"
],
"configurationItems": [
"vm01"
],
"originAlertId": "63b6a1c5-3552-4676-8073-c31e2641f787_microsoft.insights_metricalerts_AlertMetricCPUPercentage_-1419778843",
"firedDateTime": "2021-05-21T18:20:57.1495223Z",
"description": "if CPU % is less than 10%",
"essentialsVersion": "1.0",
"alertContextVersion": "1.0"
},
"alertContext": {
"properties": null,
"conditionType": "MultipleResourceMultipleMetricCriteria",
"condition": {
"windowSize": "PT5M",
"allOf": [
{
"metricName": "Percentage CPU",
"metricNamespace": "Microsoft.Compute/virtualMachines",
"operator": "LessThan",
"threshold": "10",
"timeAggregation": "Maximum",
"dimensions": [],
"metricValue": 0.95,
"webTestName": null
}
],
"windowStartTime": "2021-05-21T18:12:44.375Z",
"windowEndTime": "2021-05-21T18:17:44.375Z"
}
}
}
}
As stated above it's just JSON data so you'll just want to create a C# class mapped to the properties you're interested in and then deserialize the data to an object of that class.
Here is a snippet from the Microsoft docs on deserializing JSON data
using System;
using System.Collections.Generic;
using System.Text.Json;
namespace DeserializeExtra
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
public string SummaryField;
public IList<DateTimeOffset> DatesAvailable { get; set; }
public Dictionary<string, HighLowTemps> TemperatureRanges { get; set; }
public string[] SummaryWords { get; set; }
}
public class HighLowTemps
{
public int High { get; set; }
public int Low { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
#"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""TemperatureCelsius"": 25,
""Summary"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00-07:00"",
""2019-08-02T00:00:00-07:00""
],
""TemperatureRanges"": {
""Cold"": {
""High"": 20,
""Low"": -10
},
""Hot"": {
""High"": 60,
""Low"": 20
}
},
""SummaryWords"": [
""Cool"",
""Windy"",
""Humid""
]
}
";
WeatherForecast weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Console.WriteLine($"Date: {weatherForecast.Date}");
Console.WriteLine($"TemperatureCelsius: {weatherForecast.TemperatureCelsius}");
Console.WriteLine($"Summary: {weatherForecast.Summary}");
}
}
}
// output:
//Date: 8/1/2019 12:00:00 AM -07:00
//TemperatureCelsius: 25
//Summary: Hot
And here is the actual article
https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?pivots=dotnet-5-0
I have stored JSON data in a string and by using the JObject, I am trying to get values from JSON data. I am just not able to figure out that what is the underlying issue with my code because I am not able to get data from the JSON object. A snippet of my code is attached below. If some can help me out to figure out the issue it will be immensely appreciated.
String text;
try {
var response = (HttpWebResponse)request.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
JObject jObject = JObject.Parse(text);
string haha = (string)jObject["value/segments/requests/count/sum"];
ViewBag.gotstring = haha;
}
System.Diagnostics.Debug.WriteLine(text);
} catch(Exception e) {
System.Diagnostics.Debug.WriteLine(url);
System.Diagnostics.Debug.WriteLine(e.ToString()); }
return View();
Here is the JSON:
{
"value": {
"start": "2018-08-12T04:44:38.941Z",
"end": "2018-08-12T16:44:38.941Z",
"interval": "PT30M",
"segments": [
{
"start": "2018-08-12T14:00:00Z",
"end": "2018-08-12T14:30:00Z",
"segments": [
{
"requests/count": {
"sum": 2
},
"request/name": "GET Home/Index"
},
{
"requests/count": {
"sum": 1
},
"request/name": "GET Home/About"
},
{
"requests/count": {
"sum": 1
},
"request/name": "GET Home/Contact"
}
]
},
{
"start": "2018-08-12T14:30:00Z",
"end": "2018-08-12T15:00:00Z",
"segments": [
{
"requests/count": {
"sum": 2
},
"request/name": "GET Account/Register"
},
{
"requests/count": {
"sum": 1
},
"request/name": "GET Account/Login"
}
]
},
{
"start": "2018-08-12T15:30:00Z",
"end": "2018-08-12T16:00:00Z",
"segments": [
{
"requests/count": {
"sum": 8
},
"request/name": "GET Home/Index"
},
{
"requests/count": {
"sum": 8
},
"request/name": "GET Home/About"
}
]
}
]
}
}
jObject does not work this way. It returns dictionary that you can query by key, but keys are single level. I.e. you'll be able to get some data like this:
var haha = jObject["value"]["segments"];
But beyond that it gets very complex. You'll be much better off defining a C# class that represents your JSON and serialise into that. A simple `Edit=>Paste Special => JSON as Class" in Visual Studio gives this:
public class Rootobject
{
public Value value { get; set; }
}
public class Value
{
public DateTime start { get; set; }
public DateTime end { get; set; }
public string interval { get; set; }
public Segment[] segments { get; set; }
}
public class Segment
{
public DateTime start { get; set; }
public DateTime end { get; set; }
public Segment1[] segments { get; set; }
}
public class Segment1
{
[JsonProperty("requests/count")]
public RequestsCount requestscount { get; set; }
[JsonProperty("request/name")]
public string requestname { get; set; }
}
public class RequestsCount
{
public int sum { get; set; }
}
and then deserialise like this:
var serialised = JsonConvert.DeserializeObject<Rootobject>(json);
var haha = serialised.value.segments.FirstOrDefault().segments.FirstOrDefault().requestscount.sum;
And here is a working sample: https://dotnetfiddle.net/CZgMNE
Can you try:
EDIT: seems like segments is an array, this will get you the sum for first segment only
string haha = (string)jObject["value"]["segments"][0]["segments"]["requests/count"]["sum"];
Okay first of all, the answer is probably very simple... But after 45 minutes of trying and googling I just can't figure it out!
So I have some problems getting this Json to parse correctly. I created the classes with http://json2csharp.com/ only it doesn't tell me the code to parse it.
My current classes:
public class Representations
{
public string thumb { get; set; }
public string large { get; set; }
public string full { get; set; }
}
public class Search
{
public string id { get; set; }
public string file_name { get; set; }
public Representations representations { get; set; }
}
public class SearchQuery
{
public List<Search> search { get; set; }
public int total { get; set; }
}
JSON:
{
"search": [
{
"id": "0300",
"file_name": "0300.JPG",
"representations": {
"thumb": "thumb.jpg",
"large": "large.jpg",
"full": "0300.jpg"
},
},
{
"id": "0000",
"file_name": "0000.JPG",
"representations": {
"thumb": "thumb.jpg",
"large": "large.jpg",
"full": "0000.jpg"
},
},
{
"id": "0d00",
"file_name": "0d00.JPG",
"representations": {
"thumb": "thumb.jpg",
"large": "large.jpg",
"full": "0d00.jpg"
},
}
],
"total": 3
}
and code:
searchresults = JsonConvert.DeserializeObject<List<SearchQuery>>(JSONCode);
You should deserialize to a SearchQuery, not List<SearchQuery>:
SearchQuery result = JsonConvert.DeserializeObject<SearchQuery>(JSONCode);
and then use the search property to access the list of search results:
List<Search> searchResults = result.search;