Home > Software engineering >  C# dynamic anonymous JSON definition
C# dynamic anonymous JSON definition

Time:10-28

I have a rather large JSON file I am attempting to parse and set definitions for in C#. I am getting an error from the Newtonsoft JSON Deserializer.

Newtonsoft.Json.JsonSerializationException: 'Error converting value 151 to type 'QA_Test1.json.states'. Path 'MyFlow.states[1]', line 8378, position 15.'

-       InnerException  {"Could not cast or convert from System.Int64 to QA_Test1.json.states."}    System.Exception {System.ArgumentException}

Because this element is an array [] and has a nested list, side by side with anonymous integers. I'm stuck here

"states": [
  { .. some more json data 
  },
  12,
  14,
  9,
  10
]

The first problem (1) I don't even need the integer data, I need the nested data but the Newtonsoft Deserializer is still trying to deserialize the integer data without a def.

The second problem (2) The "variables" element has anonymous elements also, I want to get the names example anonomousVarName1 and get the properties of that item. But I wont know what they are. So having a definition I am finding difficult.

"states": [
  { .. some more json data 
  },
  12, // problem 1
  14,
  9,
  10
],
"variables": {
        "anonomousVarName1": {
            "blah": ".VariableImpl",
            "blah": 407
            },
            "blah": false,
            "blah": null
        },
        "anonomousVarName2": {
            {
            "blah": ".VariableImpl",
            "blah": 407
            },
            "blah": false,
            "blah": null
            }
        }

My definition

public class state_connections
{
    [JsonProperty("states")]
    public List<states> states { get; set; }

    [JsonProperty("variables")]
    public Dictionary<string, variables> variables { get; set; } // added resolution for problem 2
}

Problem #1 remains a huge issue problem #2 is resolved by using

Dictionary<string, variables> variables {get; set;}

Accessing the Dictionary variables

connections_def file = JsonConvert.DeserializeObject<connections_def>(_data_file, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, MaxDepth = 200, NullValueHandling = NullValueHandling.Ignore });
           
            foreach(var variable in file.automatonFlow.variables)
            {
                Console.WriteLine();
                Console.WriteLine($"Variable Key Name: {variable.Key}");
                Console.WriteLine("--- properties ---");
                Console.WriteLine($"    @class: {variable.Value.@class}");
                Console.WriteLine($"    @id: {variable.Value.id}");
                Console.WriteLine($"    defaultValue: {variable.Value.defaultValue}");
                Console.WriteLine($"    id: {variable.Value.long_id}");
                Console.WriteLine($"    name: {variable.Value.name}");
                Console.WriteLine($"    notes: {variable.Value.notes}");
                Console.WriteLine($"    secure: {variable.Value.secure}");
                Console.WriteLine($"    stateId: {variable.Value.stateId}");
                Console.WriteLine($"    type: {variable.Value.type}");
            }

CodePudding user response:

Thank you Rivo for your assistance as clearly this could not be done without implementing List object. Still open to suggestions but here is what I found as a work-around and this is by far, a hack for a horribly designed JSON.

        foreach(var state in file.automatonFlow.states)
        {
            //check if object is actually the json I want and not the stupid integers
            if (state.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
            {
                Console.WriteLine("--- states ---");

                //convert the object BACK into text
                var jobject = (JsonConvert.SerializeObject(state));

                //convert the data BACK into definition form
                states states = JsonConvert.DeserializeObject<states>(jobject, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, MaxDepth = 200, NullValueHandling = NullValueHandling.Ignore });

                Console.WriteLine($"    @id: {states.id}");
                Console.WriteLine($"    actionClass: {states.actionClass}");
                Console.WriteLine($"    name: {states.name}");
                Console.WriteLine();
            }   
        }
        Console.ReadLine();

Definition

 public class connections_def
{
    [JsonProperty("states")]
    public List<object> states  { get; set; }

    [JsonProperty("variables")]
    public Dictionary<string, variables> variables { get; set; }
}

---Outputs----

--- states ---

@id: 1
actionClass: HostCommandAction
name: Check Service running

CodePudding user response:

In your case, using List<object> is more appropriate.

So your class definition should be :

public class state_connections
{
    [JsonProperty("states")]
    public List<object> states { get; set; }

    [JsonProperty("variables")]
    public Dictionary<string,string> variables { get; set; }
}
  • Related