Home > database >  Reading and Writing Nested data JSON in C#
Reading and Writing Nested data JSON in C#

Time:06-15

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

CodePudding user response:

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;

CodePudding user response:

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>();
}

CodePudding user response:

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);
  • Related