简体   繁体   中英

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM