Reputation: 503
This is the Json that I am reading from a (.)json file.
{
"steps": [
{
"stepType": "runFolderUpdate",
"stepData": {
"actionType": "update",
"folderData": {
"folderName": "New Folder 1",
"dirName": "C:/demo/demo.xml",
"machineAddress": "10.23.44.12"
}
}
},
{
"stepType": "runFolderCreate",
"stepData": {
"actionType": "create",
"actionData": {
"folderName": "New Folder 2",
"dirName": "C:/Demo",
"machineAddress": "10.23.211.2"
}
}
},
{ . . . },
{ . . . }
]
}
My requirement is to get an Array out of this Json so that I can have all the fields and can access it with help of "stepType" and further with the help of "actionType" value.
For stepType = "runFolderUpdate"
{
"stepType": "runFolderUpdate",
"stepData": {
"actionType": "update",
"folderData": {
"folderName": "New Folder 1",
"dirName": "C:/demo/demo.xml",
"machineAddress": "10.23.44.12"
}
}
}
For stepType = "runFolderCreate"
{
"stepType": "runFolderCreate",
"stepData": {
"actionType": "create",
"actionData": {
"folderName": "New Folder 2",
"dirName": "C:/Demo",
"machineAddress": "10.23.211.2"
}
}
}
So now that I have two blocks, one for create and one for update, I can go on and access values per requirement and I am not restricted to how the JSON keys are arranged.
I tried to do it using JsonReader from Newtonsoft library but the problem is it is only forward moving reader and I can not go back. Now since this is a JSON file we are talking about, so order of how the Keys are placed should not matter but with JsonReader I get my hands tied.
Lets say for example, I am if stepType is below stepData then I can not use a JsonReader to go back to stepData afetr I know what type of stepType I am talking about.
I am looking on an approach on how to convert this steps object Json to array and each blob will be act as a block of information which I can access (Just like we do in array, using index so I dont have to worry about the order of keys.
////////UPDATE////////
I am trying to do something like this....
JObject object = Read Json from file...
JArray array = object.get("steps");
Now that I have array, based on stepType I can work on...
is this even possible?
Upvotes: 2
Views: 319
Reputation: 1128
You can use JObject, JToken and JArray for your for work.
Say for your Json, your Json starts with an object...it has a "[" followed which is representation of an Array i.e. JArray...so you can do something like this...
So once you get "steps" as object like this...
JObject obj= null;
using (StreamReader file = File.OpenText(filePath))
using (JsonTextReader reader = new JsonTextReader(file))
{
obj = (JObject)JToken.ReadFrom(reader);
}
JToken token = obj.GetValue("steps");
JArray array = (JArray) token;
Now that you have an array which looks like this...since it has read "steps" already
[
{ .... },
{ .... }
]
Every curly brace is you array index (here Json object) you can reach using for loop...
for (int i = 0; i < array.length(); i++) {
//Now here get the next token which is an object again so you can
//parse through it and perform your action as needed for create or update
}
This is a same as java.
Dont worry about order of keys, JObject gives you freedom and you DO NOT NEED a model for this...Model is sure cleaner way to do, but it is tightly coupled, so if your Json changes, its of no use.
Please mark as answer if you feel this is correct.
Upvotes: 1
Reputation: 119136
You can convert all this to C# classes fairly easily with a custom converter. Newtonsoft gives some really useful extensibility points. So, lets say you had the following class structure:
public class Root
{
public List<Step> Steps { get; set; }
}
// Here we are telling the serialiser to use the converter
[JsonConverter(typeof(StepConverter))]
public class Step
{
public string StepType { get; set; }
public IStepData StepData { get; set; }
}
public interface IStepData
{
string ActionType { get; set; }
}
public class RunFolderUpdate : IStepData
{
public string ActionType { get; set; }
//etc - you can fill in the rest here
}
public class RunFolderCreate : IStepData
{
public string ActionType { get; set; }
//etc - you can fill in the rest here
}
Now we can implement the converter like this:
public class StepConverter : JsonConverter<Step>
{
public override Step ReadJson(JsonReader reader, Type objectType,
[AllowNull] Step existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var step = JObject.ReadFrom(reader);
var stepType = step["stepType"].Value<string>();
switch(stepType)
{
case "runFolderUpdate":
return new Step
{
StepType = stepType,
StepData = step["stepData"].ToObject<RunFolderUpdate>()
};
case "runFolderCreate":
return new Step
{
StepType = stepType,
StepData = step["stepData"].ToObject<RunFolderCreate>()
};
}
throw new Exception("Errr, unknown step type!");
}
public override void WriteJson(JsonWriter writer, [AllowNull] Step value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
And finally you can deserialise like this:
var result = JsonConvert.DeserializeObject<Root>(json);
Upvotes: 2