How to deserialize JSON file to C# object by section - c#

I have 2 C# class:
public class Light
{
public int Brightness { get; set; }
public string Mode { get; set; }
}
public class AirConditioner
{
public int Temperature{ get; set; }
public string Mode { get; set; }
}
JSON file format:
{
"Light": {
"Brightness": 5,
"Mode": "On"
},
"AirConditioner": {
"Temperature": 25,
"Mode": "Cooling"
}
}
I want to parse JSON file to C# by section, something like this:
var light = JsonDeserialize<Light>.(FileSection["Light"]);
var aircon = JsonDeserialize<AirConditioner>.(FileSection["AirConditioner"]);
What I want is the same as Asp.Net Core configuration work:
var light = new Light();
Configuration.GetSection("Light").Bind(light);
It will be better if I do not need to install other packages.
Thank you for your help.
Update:
The problem is how to get a section of the JSON file.
If I can get the Light section like this:
var lightString = JsonFile.GetSection("Light");
Then I can simply deserialize with System.Text.Json namespace:
var light = JsonSerializer.Deserialize<Light>(lightString);

I have done this by creating a parent class that holds the Light and AirConditioner properties.
The parent Class:
public class Devices
{
public Light Light {get;set;}
public AirConditioner AirConditioner {get;set;}
}
Then you can de-serialize into the Devices and access the light and airconditioner.
var devices = JsonDeserialize<Devices>.(myjsonfilecontent);
var light = devices.Light;
var aircon = devices.AirConditioner;

I think you're looking for https://www.newtonsoft.com/json/help/html/SerializingJSONFragments.htm in Newtonsoft's JSON.Net
It allows for manipulating of a whole JSON object as very generic JOBject and locating and converting only the parts you need.
In your example this looks something like the following. This code uses the newtonsoft.json package.
using System;
using Newtonsoft.Json.Linq;
namespace SO_67293726
{
public class Light
{
public int Brightness { get; set; }
public string Mode { get; set; }
}
public class AirConditioner
{
public int Temperature { get; set; }
public string Mode { get; set; }
}
class Program
{
public static string JsonString =>
#"{
""Light"": {
""Brightness"": 5,
""Mode"": ""On""
},
""AirConditioner"": {
""Temperature"": 25,
""Mode"": ""Cooling""
}
}";
static void Main(string[] args)
{
var jobject = JObject.Parse(JsonString);
var light = jobject["Light"].ToObject<Light>();
var aircon = jobject["AirConditioner"].ToObject<AirConditioner>();
}
}
}

Related

Reading and Writing Nested data JSON in C#

I have looked at several solutions over the web on reading nested json files but I haven't found one suitable to my need. Maybe because I am new to JSON. Here is my issue:
I have the following JSON in a file:
{
"ConfigError" : {
"DateSent": "2022-04-28T14:03:16.6628493-07:00",
"ToolType": "WSM",
"IsSent": true
},
"FileCopyError" : {
"DateSent": "2022-06-14T14:03:16.6628493-07:00",
"ToolType": "RMT",
"IsSent": false
}
}
For this I have written two classes. One for the Inner object:
public class SummaryEmailStatus
{
public DateTime DateSent { get; set; }
public string ToolType { get; set; }
public bool IsSent { get; set; }
}
One for the Outer Objects:
public class SummaryEmailClass
{
SummaryEmailStatus Status { get; set; } = new SummaryEmailStatus();
}
I would like to be able to read the JSON in C#. I'm primarily concerned with the inner objects. They are of same class but they need to be used differently. So ideally I'd want a function that I can pass in "ConfigError" or "FileCopyError" into and it will return SummaryEmailStatus class object populated by the values in the JSON:
public static void ReadJasonFile(string jsonFileName, string objctName)
{
List<SummaryEmailClass> emailClassList = new List<SummaryEmailClass>();
dynamic jsonFile = JsonConvert.DeserializeObject(File.ReadAllText(jsonFileName));
SummaryEmailStatus sumclass = jsonFile[objctName];
}
But this gives me a run time error saying:
Cannot implicitly convert type "Newtonsoft.Json.Linq.JObject to SummaryEmailStatus
How can I successfully parse out the inner summaryemailstatus objects?
Additionally, I'd like to be able to create the JSON data within C#. The reason being, when I read the JSON, I will do some task and then will need to update the values of the JSON with the current timestamps. I'd imagine, I'd need to rewrite the file. How can I write a nested JSON like this in C#?
If JSON is not the best way to do this, I am open to alternatives
you can try
string json = File.ReadAllText(jsonFileName);
Dictionary<string,SummaryEmailStatus> summaryEmailStatus =
JsonConvert.DeserializeObject<Dictionary<string,SummaryEmailStatus>>(json);
you can use it
SummaryEmailStatus configError = summaryEmailStatus["ConfigError"];
if you want update data
summaryEmailStatus["ConfigError"].DateSent= DateTime.Now;
and serialize back
json = JsonConvert.SerializeObject(summaryEmailStatus);
or if you have only 2 main properties, create a class
public class SummaryEmailClass
{
SummaryEmailStatus ConfigError { get; set; }
SummaryEmailStatus FileCopyError{ get; set; }
}
and use it
SummaryEmailClass summaryEmailStatus =
JsonConvert.DeserializeObject<SummaryEmailStatusClass>(json);
SummaryEmailStatus configError = summaryEmailStatus.ConfigError;
Summary
You need to convert your JObject into the type you are expecting, as shown here:
SummaryEmailStatus sumclass = jsonFile[objctName].ToObject<SummaryEmailStatus>();
Details
jsonFile[objtName] is of type JObject. The reason is because JsonConvert.DeserializeObject has no idea that you intend to convert that into a list of SummaryEmailStatus.
Once you have your array of JObjects, you can convert that into a SummaryEmailStatus as shown in the following snippet:
public static void ReadJasonFile(string jsonFileName, string objctName)
{
List<SummaryEmailClass> emailClassList = new List<SummaryEmailClass>();
dynamic jsonFile = JsonConvert.DeserializeObject(File.ReadAllText(jsonFileName));
SummaryEmailStatus sumclass = jsonFile[objctName].ToObject<SummaryEmailStatus>();
}
Easy way is kept both objects in JSON, I rewrite your code and add root. For example, if you want to write Config Error and don't write File Copy Error, you can save one of them like null.
public class ConfigError
{
public DateTime DateSent { get; set; }
public string ToolType { get; set; }
public bool IsSent { get; set; }
}
public class FileCopyError
{
public DateTime DateSent { get; set; }
public string ToolType { get; set; }
public bool IsSent { get; set; }
}
public class Root
{
public ConfigError ConfigError { get; set; }
public FileCopyError FileCopyError { get; set; }
}
//in your method to get all data
var json = File.ReadAllText(jsonFileName);
var myDeserializedClass = JsonConvert.DeserializeObject<Root>(json);
Example change config and write to file
var json = #"{
""ConfigError"" : {
""DateSent"": ""2022-04-28T14:03:16.6628493-07:00"",
""ToolType"": ""WSM"",
""IsSent"": true
},
""FileCopyError"" : {
""DateSent"": ""2022-06-14T14:03:16.6628493-07:00"",
""ToolType"": ""RMT"",
""IsSent"": false
}
}";
var conf = JsonConvert.DeserializeObject<Root>(json);
conf.ConfigError.DateSent = DateTime.Now;
conf.ConfigError.ToolType = "New way";
conf.ConfigError.IsSent = false;
conf.FileCopyError = null;
var newJson = JsonConvert.SerializeObject(conf);
File.WriteAllText("your path", newJson);

How to convert a class instance to JsonDocument?

Let's say we have an entity class that looks like this:
public class SerializedEntity
{
public JsonDocument Payload { get; set; }
public SerializedEntity(JsonDocument payload)
{
Payload = payload;
}
}
According to npsql this generates a table with column payload of type jsonb for this class which is correct.
Now what I would like to do is take any class instance and store it as payload in this table e.g.:
public class Pizza {
public string Name { get; set; }
public int Size { get; set; }
}
should then be possible to be retrieved as an object with following structure:
{Name: "name", Size: 10}
So I need something like this:
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(someConverter.method(pizza))
You can use JsonSerializer.SerializeToDocument which was added in .NET 6. In your case you would end up with this:
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(JsonSerializer.SerializeToDocument(pizza))
With System.Text.Json it's a little awkward but possible:
using System.Text.Json;
using System.Text.Json.Serialization;
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(JsonDocument.Parse(JsonSerializer.Serialize(pizza)));
It has been built-in to dotnet core since (I think) v3.0, so you do not need any additional 3rd party libs. Just don't forget the usings.
There may be some tricks to get the parsing a little more efficient, though (using async API, perhaps or as Magnus suggests by serializing to binary using SerializeToUtf8Bytes).
I haven't been able to find any approach that goes directly from T or object to JsonDocument. And I cannot believe this is not possible somehow. Please leave a comment if you know how that works or add your answer.
Serailize it and than parse it to JsonDocument.
var doc = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(
new Pizza {Name = "Calzone", Size = 10}));
If your EF entity (SerializedEntity) will always have a Pizza as its serialized JSON document, then you can simply use POCO mapping - replace the JsonDocument property with a Pizza property, and map it to a jsonb column.
If the actual types you want vary (sometimes Pizza, sometimes something else), you can also map an object property to jsonb, and assign whatever you want to it. Npgsql will internally serialize any object to JSON:
class Program
{
static void Main()
{
using var ctx = new BlogContext();
ctx.Database.EnsureDeleted();
ctx.Database.EnsureCreated();
ctx.FoodEntities.Add(new FoodEntity { SomeJsonFood = new Pizza { Name = "Napoletana" } });
ctx.FoodEntities.Add(new FoodEntity { SomeJsonFood = new Sushi { FishType = "Salmon" } });
ctx.SaveChanges();
}
}
public class BlogContext : DbContext
{
public DbSet<FoodEntity> FoodEntities { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("...");
}
public class FoodEntity
{
public int Id { get; set; }
public string Name { get; set; }
[Column(TypeName = "jsonb")]
public object SomeJsonFood { get; set; }
}
public class Pizza
{
public string Name { get; set; }
public int Size { get; set; }
}
public class Sushi
{
public string FishType { get; set; }
}
Final solution for me:
public class SerializedEntity
{
public object? Payload { get; set; }
public SerializedEntity(object? payload)
{
Payload = payload;
}
}
and the EF configuration for it:
public void Configure(EntityTypeBuilder<SerializedEntity> builder)
{
builder.Property(n => n.Payload).HasColumnType("jsonb").HasConversion(
v => JsonConvert.SerializeObject(v,
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}),
v => JsonConvert.DeserializeObject<object?>(v,
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}));
}

JSON Newtonsoft C# - Deserialize specific fields in JSON file

I am working with a huge JSON file, where is just needed to extract some fields inside it. I've been searching some ways to deserialize, but don't want to create the whole Class and Object in C# with all the fields inside the JSON, this would be a lot of useless memory.
I can get the JSON file using a Webclient:
using (WebClient wc = new WebClient())
{
jsonWeb = wc.DownloadString("http://link_to_get_JSON");
}
//Deserialize into a JObject
JObject obj = JObject.Parse(jsonWeb);
//Tried to access the info with
var val = obj.PropTwo;
var solution = obj.Descendants().OfType<JProperty>().Where(p => p.Name == "solverSolution").Select(x => x.Value.ToString()).ToArray();
I really could not find a way to get the wanted fields inside the JObject.
Inside the JSON, the only information is needed is the solverSolution:{} below:
{
"content":
[
{
"id":"f4d7e7f5-86ab-4155-8336-ca5f552cb3b4",
"name":"m1",
"description":"m1",
"maxHeight":2000.0,
"layers":6,
"pallet":{},
"product":{},
"solverSolution":
{
"id":"106ef605-d95e-4c74-851b-63310fbcbc7d",
"name":"solver",
"maxHeight":2000.0,
"layers":6,
"solution":[
{
"X1":0,
"Y1":0,
"Z1":0,
"X2":296,
"Y2":246,
"Z2":220
},
...
"default":false
},
"customSolutions":[0]
},
{},
...
],
"pageable":{},
"totalPages":1,
"last":true,
"totalElements":7,
"first":true,
"sort":{},
"number":0,
"numberOfElements":7,
"size":20
}
Here I leave my appreciation and gratitude for the community beforehand. Cheers,
André Castro.
Then use only the desired properties in your object, making sure to follow the structure of the desired model.
public partial class RootObject {
[JsonProperty("content")]
public Content[] Content { get; set; }
}
public partial class Content {
[JsonProperty("solverSolution")]
public SolverSolution SolverSolution { get; set; }
}
public partial class SolverSolution {
[JsonProperty("id")]
public Guid Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("maxHeight")]
public double MaxHeight { get; set; }
[JsonProperty("layers")]
public long Layers { get; set; }
[JsonProperty("solution")]
public Solution[] Solution { get; set; }
[JsonProperty("default")]
public bool Default { get; set; }
}
public partial class Solution {
[JsonProperty("X1")]
public long X1 { get; set; }
[JsonProperty("Y1")]
public long Y1 { get; set; }
[JsonProperty("Z1")]
public long Z1 { get; set; }
[JsonProperty("X2")]
public long X2 { get; set; }
[JsonProperty("Y2")]
public long Y2 { get; set; }
[JsonProperty("Z2")]
public long Z2 { get; set; }
}
The parser will ignore the rest that do not map to properties of the object model.
var root = Jsonsonvert.DeserializeObject<RootObject>(jsonWeb);
var solverSolution = root.Content[0].SolverSolution;
How can I get all SolverSolution
SolverSolution[] solutions = root.Content.Select(content => content.SolverSolution).ToArray();
I use:
JsonConvert.DeserializeObject<dynamic>(stringInput)
to get anonymouse type I need
Then you can use something like this to get specific part:
var obj = JsonConvert.DeserializeObject<dynamic>(input)["content"][0]["solverSolution"];
It's easy and gets me job done.
Edit:
Side note, please next time when you upload json just cut off parts that are not needed so I can serialize it, took me some time to fix it :D
You can use a JObject to parse all Json. Then, you can map a specific children to your object.
Reference

json serialize Lists with newtonsoft

I would like to use newtonsoft json serialzer to create json.
I'm totaly new in building LIST and collections, so I will ask you for help.
To create a simple json will work.
I have to build a attribute list, with a attributelist.
Maybee there is an other libary, making this easier ?
I need this json:
{
"objectTypeId": 545,
"attributes": [{
"objectTypeAttributeId": 222,
"objectAttributeValues": [{
"value": "Kommentar"
}]
}]
}
So for this I startet to
public class Controller
{
public int objectTypeId { get; set; }
public IList<string> attributes { get; set; }
}
Controller controllerjson = new Controller
{
objectTypeId = 545,
// How to add the attributes with each values ?
}
Your c# class model can't match with your JSON data.
There are two way can create model easily.
You can use Web Essentials in Visual Studio, use Edit > Paste special > paste JSON as class, you can easier to know the relation between Json and model.
If you can't use Web Essentials you can instead of use http://json2csharp.com/ online JSON to Model class.
You can try to use those models to carry your JSON Format.
public class ObjectAttributeValue
{
public string value { get; set; }
}
public class Attribute
{
public int objectTypeAttributeId { get; set; }
public List<ObjectAttributeValue> objectAttributeValues { get; set; }
}
public class RootObject
{
public int objectTypeId { get; set; }
public List<Attribute> attributes { get; set; }
}
You can use like this.
RootObject controllerjson = new RootObject()
{
objectTypeId = 545,
attributes = new List<Attribute>() {
new Attribute() {
objectTypeAttributeId = 222,
objectAttributeValues = new List<ObjectAttributeValue>() {
new ObjectAttributeValue() { value= "Kommentar" }
}
}
}
};
string jsonStr = JsonConvert.SerializeObject(controllerjson);
c# online

Cannot deserialize the JSON array

I have Json like below:
[
{
"name": "ts.DatumVon",
"value": "29.10.2015"
},
{
"name": "ts.Von",
"value": "8:00"
},
{
"name": "ts.Bis",
"value": "16:30"
}
]
for this class:
public class TSInfo
{
public TimeSaver ts { get; set; }
[Display(Name = "Status")]
public TSStatus tsStatus { get; set; }
[Display(Name = "Typ")]
public TSTyp tsTyp { get; set; }
public TSAuswahlSteps step { get; set; }
}
How to deserialize this Json string in controller method?
EDIT:
I hope that clarifies it.
public class TimeSaver
{
public DateTime DatumVon { get; set; }
public TimeSpan Von { get; set; }
public TimeSpan Bis { get; set; }
}
I tried something like this:
string tsi = [{"name":"ts.DatumVon","value":"29.10.2015"},{"name":"ts.Von","value":"8:00"},{"name":"ts.Bis","value":"16:30"}]
var dict = JsonConvert.DeserializeObject<List<Dictionary<String,String>>(tsi);
The JSON you provided is a list of dictionaries. So you can deserialize it (using NewtonSoft.Json) like this:
string json = "your json";
var result = JsonConvert.Deserialize<List<Dictionary<String,String>>(json);
How you map the result to your class is up to you.
EDIT the above makes no sense. Sorry for that.
Well, your JSON gave me some headache but I think I fixed it.
The JSON is an array of KeyValuePairs. Every pair describes an attribute of your TimeSaver class. The array as an whole describes the complete class. I don't know of an easy way to convert this JSON to a C# class. What complicates the problem even more is the fact that every attribute has some sort of namespace prefix: ts. The final complication is the date format. That's not a format that's recognized automatically.
My solution converts the JSON to a new JSON describing a TimeSaver object. This new JSON is then deserialized using JsonConvert.
One issue still remains: the TimeSaver.DateVon has become a string.
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
string tsi = "[{\"name\":\"ts.DatumVon\",\"value\":\"29.10.2015\"},{\"name\":\"ts.Von\",\"value\":\"8:00\"},{\"name\":\"ts.Bis\",\"value\":\"16:30\"}]";
var attributes = JsonConvert.DeserializeObject<List<NameValuePair>>(tsi);
attributes = attributes
.Select(item => new NameValuePair { Name = item.Name.Replace("ts.", ""), Value = item.Value })
.ToList();
var newJson = "{" + String.Join(",", attributes.Select(item => String.Format("\"{0}\":\"{1}\"", item.Name, item.Value))) + "}";
Console.WriteLine(newJson);
var ts = JsonConvert.DeserializeObject<TimeSaver>(newJson);
Console.WriteLine(ts.DatumVon);
Console.WriteLine(ts.Von);
Console.WriteLine(ts.Bis);
}
}
public class NameValuePair
{
public string Name { get; set; }
public string Value { get; set; }
}
public class TimeSaver
{
public String DatumVon { get; set; }
public TimeSpan Von { get; set; }
public TimeSpan Bis { get; set; }
}

Categories