Click here to Skip to main content
14,883,082 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
This is my JSON String:
"OperationID": 7,
"Outcome": 0,
"Parameters": [
    {
        "Name": "ESPN",
        "Value": "342.342.444",
        "VariableType": "System.String"
    },
    {
        "Name": "source",
        "Value": "0",
        "VariableType": "ServiceData.Contracts.Validation.Source"
    }
],
"Registers": [
    {
        "Label": "DKE",
        "ReadingTime": "/Date(9/21/20)/",
        "Source": "Local",
        "StatusFlags": null,
        "Value": 1
    },

I'm fairly new to C# and JSON, but I've tried using
JToken token = JToken.Parse(table);
JArray entries = (JArray)token.SelectToken("Parameters[0].Name");

However that doesn't seem to work since it gives me back a compilation error that reads,
Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'Newtonsoft.Json.Linq.JArray'.'

Despite the fact that I cast (JArray) to token

What I have tried:

public static List<string> CleanOperationsTable(string liteConString)
        {
            List<string> cleanedList = new List<string>();
            SQLiteConnection liteCon = new SQLiteConnection(liteConString);
            liteCon.Open();
            DataTable dtbl = new DataTable();

            string select = "SELECT ResponseBody FROM Operations LIMIT 1";

            SQLiteCommand cmd = new SQLiteCommand(select, liteCon);
            SQLiteDataAdapter sqliteDAP = new SQLiteDataAdapter(cmd);
            sqliteDAP.Fill(dtbl);

            /// Converts the 1 column DataTable into a single string to 
            /// it's easier to parse with JSON
            string table = string.Join(Environment.NewLine, dtbl.Rows.OfType<DataRow>().Select(x => string.Join(" ; ", x.ItemArray)));

            JToken token = JToken.Parse(table);
            JArray entries = (JArray)token.SelectToken("Parameters[0].Name");

            foreach(JToken t in entries)
            {
                Console.WriteLine(t);
            }

            return cleanedList;
        }


I tried following these answers: c# - How to parse nested JSON data structure - Stack Overflow[^]

However that doesn't seem to work for me since their JSON statements has 1 more layer of wrapping than mine. Is there a library that allows me to parse through both nested and un-nested JSON strings? I'm currently using Newtonsoft.JSON package.
Posted
Updated 21-Sep-20 18:25pm

1 solution

Parameters[0].Name is a JValue. Specifically it's the string "ESPN" given the example JSON. JValue has implementations for converting common types like strings so you can do (string)jValueThatIsAString. But the value in your example will never be a JArray which is why you get the error.

I'm not really sure what you mean by "nested and un-nested" since there are no nesting differences in your sample JSON. I'm guessing you want to be able to aggregate all Name properties of objects in an array. You can do it like this:
C#
JToken token = JToken.Parse(@"
{
    ""OperationID"": 7,
    ""Outcome"": 0,
    ""Parameters"": [
        {
            ""Name"": ""ESPN"",
            ""Value"": ""342.342.444"",
            ""VariableType"": ""System.String""
        },
        {
            ""Name"": ""source"",
            ""Value"": ""0"",
            ""VariableType"": ""ServiceData.Contracts.Validation.Source""
        }
    ]
}");

//with LINQ
IEnumerable<string> entries = token
    .SelectToken("Parameters")
    .Select(p => (string)p.SelectToken("Name"));
//or
IEnumerable<JToken> entries = token.
    .SelectToken("Parameters")
    .Select(p => p.SelectToken("Name"));

//or with JSONPath
IEnumerable<JToken> entries = token.SelectTokens("$.Parameters[*].Name");

//If you were looking for getting the objects out (not just the name):
IEnumerable<JToken> entries = token.SelectTokens("$.Parameters[*]");


References:
Newtonsoft.Json.Linq Namespace[^]
LINQ to JSON[^]
JSONPath - XPath for JSON[^]

EDIT: For fun, if you do have objects with a Name property arbitrarily nested within an array called Parameters that can contain subarrays, you could retrieve all Name properties using this:
C#
IEnumerable<JToken> entries = token.SelectTokens("$.Parameters..Name");
//or if you want to be explicit that Parameters is an array
IEnumerable<JToken> entries = token.SelectTokens("$.Parameters[*]..Name");
//the recursive descent operator ".." doesn't care unlike the child operator "."

This works regardless of the nesting depth of the subarrays or objects.
   
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900