stevenlam505 Ответов: 1

Как я могу анализировать как вложенные, так и не вложенные строки JSON одновременно?


Это моя строка JSON:
"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
    },

Я довольно новичок в C# и JSON, но я пробовал использовать
JToken token = JToken.Parse(table);
JArray entries = (JArray)token.SelectToken("Parameters[0].Name");

Однако это похоже не работает так как возвращает мне ошибку компиляции которая гласит,
Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'Newtonsoft.Json.Linq.JArray'.'

Несмотря на то, что я бросил (JArray) маркер

Что я уже пробовал:

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


Я попытался следовать этим ответам: c# - Как разобрать вложенную структуру данных JSON - переполнение стека[^]

Однако это, похоже, не работает для меня, так как их операторы JSON имеют на 1 слой больше обертки, чем мои. Есть ли библиотека, которая позволяет мне анализировать как вложенные, так и не вложенные строки JSON? В настоящее время я использую Newtonsoft.Пакет JSON.

1 Ответов

Рейтинг:
11

Jon McKee

Parameters[0].Name это JValue В частности, это строка "ESPN", приведенная в Примере JSON. JValue имеет реализации для преобразования общих типов, таких как строки, так что вы можете сделать (string)jValueThatIsAString Но ценность в вашем примере никогда не будет а JArray вот почему вы получаете ошибку.

Я не совсем уверен, что вы подразумеваете под "вложенными и не вложенными", поскольку в вашем образце JSON нет никаких различий в вложенности. Я предполагаю, что вы хотите иметь возможность агрегировать все свойства имен объектов в массиве. Вы можете сделать это вот так:

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[*]");


Рекомендации:
Newtonsoft.В формате JSON.Пространство Имен Linq[^]
LINQ to JSON[^]
JSONPath - XPath для JSON[^]

EDIT: для удовольствия, если у вас есть объекты со свойством Name, произвольно вложенные в массив под названием Parameters, который может содержать подмассивы, вы можете получить все свойства Name, используя это:
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 "."

Это работает независимо от глубины вложенности подмассивов или объектов.