How Can I Use Foreach In This Json Line? - c#

I'm using RestSharp in my app and I need to iterate some part in a code.
request.AddParameter("undefined", "{\r\n \"targetType\": \"SYSTEM\",\r\n \"name\": \"xxxxxxxxxx\",\r\n \"message\": \"Daily usage exceeded\",\r\n \"active\": true,\r\n \"emails\": [\"machin#truc.com\"],\r\n \"conditions\": [{\r\n \"operator\": \"EQUALS\",\r\n \"operands\": [\r\n {\r\n \"attributeId\": \r\n {\r\n \"name\": \"system.usage.status\"\r\n }\r\n \r\n }, \r\n {\r\n \"valueStr\": \"nearing plan\"\r\n }\r\n ]\r\n },\r\n {\r\n \"operator\": \"EQUALS\",\r\n \"operands\": [\r\n {\r\n \"attributeId\": \r\n {\r\n \"name\": \"system.name\"\r\n }\r\n \r\n }, \r\n {\r\n \"valueStr\": \"SIM 89332401000006726968\"\r\n \r\n }\r\n ]\r\n },\r\n {\r\n \"operator\": \"EQUALS\",\r\n \"operands\": [\r\n {\r\n \"attributeId\": \r\n {\r\n \"name\": \"system.name\"\r\n }\r\n \r\n }, \r\n {\r\n \"valueStr\": \"SIM 89332401000006726968\"\r\n \r\n }\r\n ]\r\n }\r\n \r\n ]\r\n}", ParameterType.RequestBody);
How can I iterate that part with foreach?
{\r\n \"operator\": \"EQUALS\",\r\n \"operands\": [\r\n {\r\n \"attributeId\": \r\n {\r\n \"name\": \"system.name\"\r\n }\r\n \r\n }, \r\n {\r\n \"valueStr\": \"SIM 89332401000006726968\"\r\n \r\n }\r\n ]\r\n }\r\n

Create class which represents your json structure, take some help from http://json2csharp.com/
public class AttributeId
{
public string name { get; set; }
}
public class Operand
{
public AttributeId attributeId { get; set; }
public string valueStr { get; set; }
}
public class Condition
{
public string #operator { get; set; }
public List<Operand> operands { get; set; }
}
public class RootObject
{
public string targetType { get; set; }
public string name { get; set; }
public string message { get; set; }
public bool active { get; set; }
public List<string> emails { get; set; }
public List<Condition> conditions { get; set; }
}
After that,
var myJsonObject = JsonConvert.DeserializeObject<RootObject>(yourJsonString);
and then iterate on myJsonObject.conditions

Related

Json response transformed into new json format c#

I'm trying to convert a json input format into another json format by using c#.
The input format which is seen just below is gotten from a httpclient post request:
{
"data": {
"trafficData": {
"volume": {
"byHour": {
"edges": [
{
"node": {
"from": "2019-10-24T12:00:00+02:00",
"to": "2019-10-24T13:00:00+02:00",
"byDirection": [
{
"heading": "North",
"total": {
"volumeNumbers": {
"volume": 696
}
}
},
{
"heading": "South",
"total": {
"volumeNumbers": {
"volume": 726
}
}
}
]
}
},
{
"node": {
"from": "2019-10-24T13:00:00+02:00",
"to": "2019-10-24T14:00:00+02:00",
"byDirection": [
{
"heading": "North",
"total": {
"volumeNumbers": {
"volume": 805
}
}
},
{
"heading": "South",
"total": {
"volumeNumbers": {
"volume": 751
}
}
}
]
}
}
]
}
}
}
}
}
I wish to transform the json input to something similar to the output code just below:
{
"data":[
{
"from":"2019-10-24T12:00:00+02:00",
"to":"2019-10-24T13:00:00+02:00",
"heading":"South",
"volume":726
},
{
"from":"2019-10-24T13:00:00+02:00",
"to":"2019-10-24T14:00:00+02:00",
"heading":"South",
"volume":751
}
]
}
In c# i have tried the below code: (also in connection with creating new class objects with https://json2csharp.com/)
//o1 is the json object input
IEnumerable<JToken> jTokens = o1.Descendants().Where(p => !p.HasValues);
Dictionary<string, string> results = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) =>
{
properties.Add(jToken.Path, jToken.ToString());
return properties;
});
try this code
json = new JArray(JObject.Parse(json).SelectToken("data.trafficData.volume.byHour.edges")
.Select(o => new JObject
{
["from"] = (string)o["node"]["from"],
["to"] = (string)o["node"]["to"],
["byDirection"] = new JArray(o["node"]["byDirection"]
.Select(o => new JObject
{
["heading"] = o["heading"],
["volume"] = o["total"]["volumeNumbers"]["volume"]
}))
})).ToString();
I would personally use AutoMapper in this case.
My answer will be written using .NET 6 Web API model (with AutoMapper package obviously installed first).
I generated the C# classes with the tool you provided for my example.
Let's assume I have a Request.cs file as :
using System.Text.Json.Serialization;
namespace Something.Requests
{
// Root myDeserializedClass = JsonSerializer.Deserialize<Root>(myJsonResponse);
public class ByDirection
{
[JsonPropertyName("heading")]
public string heading { get; set; }
[JsonPropertyName("total")]
public Total total { get; set; }
}
public class ByHour
{
[JsonPropertyName("edges")]
public List<Edge> edges { get; set; }
}
public class Data
{
[JsonPropertyName("trafficData")]
public TrafficData trafficData { get; set; }
}
public class Edge
{
[JsonPropertyName("node")]
public Node node { get; set; }
}
public class Node
{
[JsonPropertyName("from")]
public DateTime from { get; set; }
[JsonPropertyName("to")]
public DateTime to { get; set; }
[JsonPropertyName("byDirection")]
public List<ByDirection> byDirection { get; set; }
}
public class Request
{
[JsonPropertyName("data")]
public Data data { get; set; }
}
public class Total
{
[JsonPropertyName("volumeNumbers")]
public VolumeNumbers volumeNumbers { get; set; }
}
public class TrafficData
{
[JsonPropertyName("volume")]
public Volume volume { get; set; }
}
public class Volume
{
[JsonPropertyName("byHour")]
public ByHour byHour { get; set; }
}
public class VolumeNumbers
{
[JsonPropertyName("volume")]
public int volume { get; set; }
}
}
Using your tool, I also created a Response.cs like this :
using System.Text.Json.Serialization;
namespace Something.Answers
{
public class Datum
{
[JsonPropertyName("from")]
public DateTime from { get; set; }
[JsonPropertyName("to")]
public DateTime to { get; set; }
[JsonPropertyName("heading")]
public string heading { get; set; }
[JsonPropertyName("volume")]
public int volume { get; set; }
}
public class Result
{
[JsonPropertyName("data")]
public List<Datum> data { get; set; }
}
}
In order to handle mapping between the two type of objects, I would create a MappingConfiguration like so :
namespace Something.Mapper
{
public class MappingConfiguration : Profile
{
public MappingConfiguration()
{
// TEST
CreateMap<Something.Requests.Node, Something.Answers.Datum>()
.ForMember(datum => datum.from, opt => opt.MapFrom(node => node.from))
.ForMember(datum => datum.to, opt => opt.MapFrom(node => node.to))
.ForMember(datum => datum.heading, opt => opt.MapFrom(node => node.byDirection.FirstOrDefault().heading))
.ForMember(datum => datum.volume, opt => opt.MapFrom(node => node.byDirection.FirstOrDefault().total.volumeNumbers))
.ReverseMap();
}
}
}
In my Program.cs, I would then Dependency Inject my MappingConfiguration with code below, before my "builder.Build()" :
var mappingConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new MappingConfiguration());
});
IMapper mapper = mappingConfig.CreateMapper();
builder.Services.AddSingleton(mapper);
Finally, within my business class, I can do something like this:
var jsonRequest = "{\r\n \"data\": {\r\n \"trafficData\": {\r\n \"volume\": {\r\n \"byHour\": {\r\n \"edges\": [\r\n {\r\n \"node\": {\r\n \"from\": \"2019-10-24T12:00:00+02:00\",\r\n \"to\": \"2019-10-24T13:00:00+02:00\",\r\n \"byDirection\": [\r\n {\r\n \"heading\": \"North\",\r\n \"total\": {\r\n \"volumeNumbers\": {\r\n \"volume\": 696\r\n }\r\n }\r\n },\r\n {\r\n \"heading\": \"South\",\r\n \"total\": {\r\n \"volumeNumbers\": {\r\n \"volume\": 726\r\n }\r\n }\r\n }\r\n ]\r\n }\r\n },\r\n {\r\n \"node\": {\r\n \"from\": \"2019-10-24T13:00:00+02:00\",\r\n \"to\": \"2019-10-24T14:00:00+02:00\",\r\n \"byDirection\": [\r\n {\r\n \"heading\": \"North\",\r\n \"total\": {\r\n \"volumeNumbers\": {\r\n \"volume\": 805\r\n }\r\n }\r\n },\r\n {\r\n \"heading\": \"South\",\r\n \"total\": {\r\n \"volumeNumbers\": {\r\n \"volume\": 751\r\n }\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n }\r\n }\r\n}";
Something.Requests.Request myRequest = JsonSerializer.Deserialize<Something.Requests.Request>(jsonRequest);
List<Something.Answers.Datum> data= new List<Something.Answers.Datum>();
foreach(var edge in myRequest.data.trafficData.volume.byHour.edges)
{
var tmp = _mapper.Map<Something.Requests.Node>(edge.node);
}
var jsonAnswer = JsonSerializer.Serialize(data);
Hope this gives you an alternative.

Chart a line graph using LINQPad

LINQPad can plot the line graph using anonymous arrays. I do have JSON content with datetime (entrytime) and numerical value (cumulative gains). How can I adapt LINQPad to chart the JSON content?
void Main()
{
// You can optionally specify a series type such as Pie, Area, Spline, etc.:
var customers = new[]
{
new { Name = "John", TotalOrders = 100 },
new { Name = "Mary", TotalOrders = 130 },
new { Name = "Sara", TotalOrders = 140 },
new { Name = "Paul", TotalOrders = 125 },
};
customers.Chart(c => c.Name, c => c.TotalOrders, Util.SeriesType.Line).Dump();
string json = "[\r\n {\r\n \"entryTime\": \"2019-01-08T00:00:01\",\r\n \"gains\": -0.00071,\r\n \"cumulativegains\": -0.00071\r\n },\r\n {\r\n \"entryTime\": \"2019-01-08T05:00:01\",\r\n \"gains\": -0.00102,\r\n \"cumulativegains\": -0.00102\r\n },\r\n {\r\n \"entryTime\": \"2019-01-08T09:00:01\",\r\n \"gains\": -0.00113,\r\n \"cumulativegains\": -0.00113\r\n },\r\n {\r\n \"entryTime\": \"2019-01-08T10:31:19\",\r\n \"gains\": -0.00236,\r\n \"cumulativegains\": -0.00236\r\n },\r\n {\r\n \"entryTime\": \"2019-01-09T20:21:34\",\r\n \"gains\": -0.00262,\r\n \"cumulativegains\": -0.00262\r\n },\r\n {\r\n \"entryTime\": \"2019-01-11T16:00:01\",\r\n \"gains\": -0.00075,\r\n \"cumulativegains\": -0.00075\r\n },\r\n ]";
json.Dump();
List<trades2plot> jsonData = JsonConvert.DeserializeObject<List<trades2plot>>(json);
jsonData.Dump();
}
public class trades2plot
{
//public int TradeNumber;
//public DateTime initializedTime;
public DateTime entryTime;
//public DateTime exitTime;
public double gains;
public double cumulativegains;
public trades2plot() { }
}
// You can define other methods, fields, classes and namespaces here
jsonData.Chart(c=>c.entryTime,c=>c.cumulativegains, Util.SeriesType.Line).Dump();
will enable plotting it as a line chart from JSON.

Deserializing Json to an Array type Propoerty

I am new to Json. I am trying to populate my object 'Sources' from json string with:
public class Sources
{
public long[] SourceIds;
}
string jsonstring = " [\r\n {\r\n \"SourceIds\": 20181234\r\n }, \r\n
{\r\n \"SourceIds\": 20181234\r\n },\r\n {\r\n \"SourceIds\":
20181234\r\n }\r\n]"
My aim is to have an object of 'Sources' with the values of 'SourceIds' populated.
Thanks in advance,
I suspect that your actual Json is like below:
string jsonstring = " [
{
\"SourceIds\": 20181234
},
{
\"SourceIds\": 20181234
},
{
\"SourceIds\": 20181234
}
]"
You can serialize your json with
var result = JsonConvert.DeserializeObject<IList<Class1>>(String)
Serialization Classes
public class Class1
{
public int SourceIds { get; set; }
}
Fiddle

Newtonsoft JSON - different JSON structure, object vs array [duplicate]

This question already has answers here:
How to handle both a single item and an array for the same property using JSON.net
(9 answers)
Closed 5 years ago.
I have this JSON structure:
[
{
"key1": "value",
"key2": "value",
"key3": "TYPE_ONE",
"extraData": {
"key4": "value",
"key5": "value",
"key6": {
"key7": {
"key8": "value",
"key9": "value",
"key10": "value"
}
}
}
},
{
"key1": "value",
"key2": "value",
"key3": "TYPE_TWO",
"extraData": {
"key4": "value",
"key5": "value",
"key6": {
"key7": [
{
"key8": "value",
"key9": "value",
"key10": "value"
},
{
"key8": "value1",
"key9": "value1",
"key10": "value1"
},
{
"key8": "value2",
"key9": "value2",
"key10": "value2"
}
]
}
}
}
]
I'm trying to deserialize it with using Newtonsoft.Json; in C#. JSON has two structures.
1. CASE -> when "key3": "TYPE_ONE", then key7 is object.
2. CASE -> when "key3": "TYPE_TWO", Then key7 is array.
If in class
public class key6
{
public key7 key7Item { get; set; }
}
key7Item is set as object works only if i get all object from response that are
"key3": "TYPE_ONE"
If i set key7Item as List then works only if all items from response are "key3": "TYPE_TWO".
Can i configure Newtonsoft parser to parse array if it got array or object if it got object?
Short answer - don't do this if you can possibly avoid it. You'll save yourself lots of complexity by giving the array a different key name.
Long answer, you can do it, but it's painful. If anyone knows how to do with without re-serializing the j-objects that are generated (i.e. keeping the json alongside the deserialized objects), I'd love to know:
private static readonly string Json = "[\r\n {\r\n \"key1\": \"value\",\r\n \"key2\": \"value\",\r\n \"key3\": \"TYPE_ONE\",\r\n \"extraData\": {\r\n \"key4\": \"value\",\r\n \"key5\": \"value\",\r\n \"key6\": {\r\n \"key7\": {\r\n \"key8\": \"value\",\r\n \"key9\": \"value\",\r\n \"key10\": \"value\"\r\n }\r\n }\r\n }\r\n },\r\n {\r\n \"key1\": \"value\",\r\n \"key2\": \"value\",\r\n \"key3\": \"TYPE_TWO\",\r\n \"extraData\": {\r\n \"key4\": \"value\",\r\n \"key5\": \"value\",\r\n \"key6\": {\r\n \"key7\": [\r\n {\r\n \"key8\": \"value\",\r\n \"key9\": \"value\",\r\n \"key10\": \"value\"\r\n },\r\n {\r\n \"key8\": \"value1\",\r\n \"key9\": \"value1\",\r\n \"key10\": \"value1\"\r\n },\r\n {\r\n \"key8\": \"value2\",\r\n \"key9\": \"value2\",\r\n \"key10\": \"value2\"\r\n }\r\n ]\r\n }\r\n }\r\n }\r\n]";
private static void Deserialize()
{
var switchers = JsonConvert.DeserializeObject<JObject[]>(Json);
var deserializedType1List = new List<TargetClass<Key6Type1>>();
var deserializedType2List = new List<TargetClass<Key6Type2>>();
foreach (var switcher in switchers)
{
if (switcher["key3"].Value<string>() == "TYPE_ONE")
{
deserializedType1List.Add(JsonConvert.DeserializeObject<TargetClass<Key6Type1>>(JsonConvert.SerializeObject(switcher)));
}
else
{
deserializedType2List.Add(JsonConvert.DeserializeObject<TargetClass<Key6Type2>>(JsonConvert.SerializeObject(switcher)));
}
}
//Do something with the objects...
}
private class TargetClass<TKey6Type>
{
public string key1 { get; set; }
public string key2 { get; set; }
public string key3 { get; set; }
public ExtraData<TKey6Type> extraData { get; set; }
}
private class ExtraData<TKey6Type>
{
public string key4 { get; set; }
public string key5 { get; set; }
public TKey6Type key6 { get; set; }
}
private class Key6Type2
{
public Key7[] key7 { get; set; }
}
private class Key6Type1
{
public Key7 key7 { get; set; }
}
private class Key7
{
public string key8 { get; set; }
public string key9 { get; set; }
public string key10 { get; set; }
}

Serialize an ASP.NET MVC model in JSON

I have a model like this
public class Category : BaseFieldsTables
{
public ICollection<Category> Categories { get; set; }
public Category Parent { get; set; }
public int? ParentId { get; set; }
}
i want to serialize the model to json and this is my controller
var categories =
_efCategory.List().ToList().
ToList().
Select(x => new {id = x.Id, title = x.Name, children = x.Parent});
string output = JsonConvert.SerializeObject(categories, Formatting.Indented,
new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects
});
return Json(output.Replace, JsonRequestBehavior.AllowGet);
but i get this result
"[\r\n {\r\n \"$id\": \"1\",\r\n \"id\": 1,\r\n \"title\": \"News\",\r\n \"children\": null\r\n },\r\n {\r\n \"$id\": \"2\",\r\n \"id\": 2,\r\n \"title\": \"2012\",\r\n \"children\":
{\r\n \"$id\": \"3\",\r\n \"Categories\": [\r\n {\r\n \"$id\":
This is normal. All you are seeing is the escaped version of your string (probably directly in Visual Studio). \r\n is the equivalent of a newline character and \" is just a means to escape the ". Outputted, this should appear as normal.

Categories