C# 解析从 GraphQL 返回的 Json 字符串 - Monday.com

发布于 2025-01-09 13:18:53 字数 5732 浏览 0 评论 0原文

我在解析 GraphQL 的 json 响应时遇到问题。问题是阵列有一半的时间会返回更多阵列。我的代码变得失控而且丑陋。

Json 文件(稍微修剪一下。它可以是 20 多个数据数组)

{
  "activity_logs": [
    {
      "data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":2165787062,\"pulse_name\":\"Tyler\",\"column_id\":\"email_address\",\"column_type\":\"email\",\"column_title\":\"Email Address\",\"value\":{\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"previous_value\":{\"email\":\"[email protected]\",\"text\":\"[email protected]\",\"changed_at\":\"2022-02-15T21:18:48.297Z\",\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"is_column_with_hide_permissions\":false,\"previous_textual_value\":\"[email protected]\"}"
    },
    {
      "data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":216578711,\"pulse_name\":\"Nicholas \",\"column_id\":\"email_address\",\"column_type\":\"email\",\"column_title\":\"Email Address\",\"value\":{\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"previous_value\":{\"email\":\"[email protected]\",\"text\":\"[email protected]\",\"changed_at\":\"2022-02-16T04:44:52.046Z\",\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"is_column_with_hide_permissions\":false,\"previous_textual_value\":\"[email protected]\"}"
    },
    {
      "data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":216578711,\"pulse_name\":\"Nicholas \",\"column_id\":\"batch_5\",\"column_type\":\"text\",\"column_title\":\"Batch #\",\"value\":{\"value\":\"75\"},\"previous_value\":{\"value\":\"74\"},\"is_column_with_hide_permissions\":false}"
    },
    {
      "data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"pulse_id\":216578711,\"is_top_group\":false,\"value\":{\"name\":\"Nicholas \"},\"previous_value\":{\"name\":\"Nicholas \"},\"column_type\":\"name\",\"column_title\":\"Name\"}"
    }
  ]
}

放弃制作后随机“让它工作”尝试是基于类的列表。 IContainer 中的 IContainer 变得非常复杂。

var responseData = JObject.Parse(responseText).SelectToken("data").SelectToken("boards").SelectToken("activity_logs");
dynamic updatedRecords = JsonConvert.DeserializeObject(responseData.ToString());

foreach (var record in updatedRecords)
{
List<Dictionary<string, string>> records = new List<Dictionary<string, string>>();
Dictionary<string, string> fields = new Dictionary<string, string>();
dynamic updates = JsonConvert.DeserializeObject(JObject.Parse(record.ToString()).SelectToken("data").ToString());
foreach(var update in updates)
{
    switch (update.Name.ToString())
    {
        case "column_id":
            fields.Add(update.Name.ToString(), update.Value.ToString());
            break;
        case "pulse_name":
            fields.Add(update.Name.ToString(), update.Value.ToString());
            break;
        case "value":
            dynamic values = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
            if (update.Name.ToString().Contains("column_settings"))
            {
                foreach (var value in values)
                {
                    dynamic columns = JsonConvert.DeserializeObject(JObject.Parse(value.Value.ToString()));
                    foreach(var column in columns)
                    {
                        fields.Add($"Value_{column.Name.ToString()}", column.Value.ToString());
                    }
                                                
                }
            }
            else
            {
                foreach (var value in values)
                {
                    fields.Add($"Value_{value.Name.ToString()}", value.Value.ToString());
                }
            }
                                        
            break;
        case "previous_value":
            dynamic prevValues = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
            foreach (var prevalue in prevValues)
            {
                fields.Add($"Prevalue_{prevalue.Name.ToString()}", prevalue.Value.ToString());
            }
            break;
        case "previous_textual_value":
            fields.Add(update.Name.ToString(), update.Value.ToString());
            break;
    }
}
if (fields.Count > 0)
{
    records.Add(fields);
    fields.Clear();
}
}

我的错误当我到达:

dynamic values = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
-       $exception  {"The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject(string)' has some invalid arguments"} Microsoft.CSharp.RuntimeBinder.RuntimeBinderException

解决方案是一个很大的帮助并导致我的答案。问题是 Activity_logs 数据中带有转义字符,因此字符串包含 \\"。 我必须使用 Replace("\\", "") 和 Replace("\"{", "{") 和 Replace("}\""), "}") 格式化数据部分。这使得字符串可以作为 Json 文件读取。

I'm running into issues parsing a json reponse from GraphQL. The issue is the array will come back with more arrays half the time. My code is just getting out of hand and ugly.

Json file (trimmed it a bit. It can be 20+ data arrays)

{
  "activity_logs": [
    {
      "data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":2165787062,\"pulse_name\":\"Tyler\",\"column_id\":\"email_address\",\"column_type\":\"email\",\"column_title\":\"Email Address\",\"value\":{\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"previous_value\":{\"email\":\"[email protected]\",\"text\":\"[email protected]\",\"changed_at\":\"2022-02-15T21:18:48.297Z\",\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"is_column_with_hide_permissions\":false,\"previous_textual_value\":\"[email protected]\"}"
    },
    {
      "data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":216578711,\"pulse_name\":\"Nicholas \",\"column_id\":\"email_address\",\"column_type\":\"email\",\"column_title\":\"Email Address\",\"value\":{\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"previous_value\":{\"email\":\"[email protected]\",\"text\":\"[email protected]\",\"changed_at\":\"2022-02-16T04:44:52.046Z\",\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"is_column_with_hide_permissions\":false,\"previous_textual_value\":\"[email protected]\"}"
    },
    {
      "data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":216578711,\"pulse_name\":\"Nicholas \",\"column_id\":\"batch_5\",\"column_type\":\"text\",\"column_title\":\"Batch #\",\"value\":{\"value\":\"75\"},\"previous_value\":{\"value\":\"74\"},\"is_column_with_hide_permissions\":false}"
    },
    {
      "data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"pulse_id\":216578711,\"is_top_group\":false,\"value\":{\"name\":\"Nicholas \"},\"previous_value\":{\"name\":\"Nicholas \"},\"column_type\":\"name\",\"column_title\":\"Name\"}"
    }
  ]
}

Random "get it to work" attempt after giving up on making is a List based on a Class. The IContainers within IContainers were getting very complex.

var responseData = JObject.Parse(responseText).SelectToken("data").SelectToken("boards").SelectToken("activity_logs");
dynamic updatedRecords = JsonConvert.DeserializeObject(responseData.ToString());

foreach (var record in updatedRecords)
{
List<Dictionary<string, string>> records = new List<Dictionary<string, string>>();
Dictionary<string, string> fields = new Dictionary<string, string>();
dynamic updates = JsonConvert.DeserializeObject(JObject.Parse(record.ToString()).SelectToken("data").ToString());
foreach(var update in updates)
{
    switch (update.Name.ToString())
    {
        case "column_id":
            fields.Add(update.Name.ToString(), update.Value.ToString());
            break;
        case "pulse_name":
            fields.Add(update.Name.ToString(), update.Value.ToString());
            break;
        case "value":
            dynamic values = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
            if (update.Name.ToString().Contains("column_settings"))
            {
                foreach (var value in values)
                {
                    dynamic columns = JsonConvert.DeserializeObject(JObject.Parse(value.Value.ToString()));
                    foreach(var column in columns)
                    {
                        fields.Add(
quot;Value_{column.Name.ToString()}", column.Value.ToString());
                    }
                                                
                }
            }
            else
            {
                foreach (var value in values)
                {
                    fields.Add(
quot;Value_{value.Name.ToString()}", value.Value.ToString());
                }
            }
                                        
            break;
        case "previous_value":
            dynamic prevValues = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
            foreach (var prevalue in prevValues)
            {
                fields.Add(
quot;Prevalue_{prevalue.Name.ToString()}", prevalue.Value.ToString());
            }
            break;
        case "previous_textual_value":
            fields.Add(update.Name.ToString(), update.Value.ToString());
            break;
    }
}
if (fields.Count > 0)
{
    records.Add(fields);
    fields.Clear();
}
}

My Error when I get to:

dynamic values = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
-       $exception  {"The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject(string)' has some invalid arguments"} Microsoft.CSharp.RuntimeBinder.RuntimeBinderException

Solution is a big help and led to my answer. The issue is the activity_logs data comes with escape characters in it so the string contains \\".
I had to format the data sections with Replace("\\", "") and Replace("\"{", "{") and Replace("}\""), "}"). This made the string readable as a Json file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

硪扪都還晓 2025-01-16 13:18:53

您必须将字符串传递给 DeserializeObject 而不是 JSON 对象。

另一种方法是将 JSON 映射到 POCO 类型,如下所示,简单的方法是在 Visual Studio 上(复制 JSON 内容,在 Visual Studio 上创建一个新的空类 -> 编辑 -> 过去的特殊 -> 粘贴JSON 作为类)

public class LogsRoot
{
    public Activity_Logs[] activity_logs { get; set; }
}

public class Activity_Logs
{
    public string data { get; set; }
}

public class DataRoot
{
    public long board_id { get; set; }
    public string group_id { get; set; }
    public bool is_top_group { get; set; }
    public long pulse_id { get; set; }
    public string pulse_name { get; set; }
    public string column_id { get; set; }
    public string column_type { get; set; }
    public string column_title { get; set; }
    public Value value { get; set; }
    public Previous_Value previous_value { get; set; }
    public bool is_column_with_hide_permissions { get; set; }
    public string previous_textual_value { get; set; }
}

public class Value
{
    public Column_Settings column_settings { get; set; }
}

public class Column_Settings
{
    public bool includePulseInSubject { get; set; }
    public bool ccPulse { get; set; }
    public string bccList { get; set; }
}

public class Previous_Value
{
    public string email { get; set; }
    public string text { get; set; }
    public DateTime changed_at { get; set; }
    public Column_Settings1 column_settings { get; set; }
}

public class Column_Settings1
{
    public bool includePulseInSubject { get; set; }
    public bool ccPulse { get; set; }
    public string bccList { get; set; }
}

然后加载 JSON 并进行如下操作,

var json = File.ReadAllText("data.json");
var rootLogs = JsonConvert.DeserializeObject<LogsRoot>(json);

Dictionary<string, string> fields = new Dictionary<string, string>();

foreach (var logJson in rootLogs.activity_logs)
{
    var log = JsonConvert.DeserializeObject<DataRoot>(logJson.data);
    fields.Add(log.column_id, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
    fields.Add(log.pulse_name, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
    fields.Add(log.previous_value.email, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
    fields.Add(log.previous_textual_value, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
}

You have to pass in a string to DeserializeObject instead of a JSON object.

Another way would be get your JSON mapped to a POCO types as follows, easy way to do is on Visual Studio (Copy your JSON contents, on Visual Studio create a new empty class -> Edit-> Past Special -> Paste JSON as classes)

public class LogsRoot
{
    public Activity_Logs[] activity_logs { get; set; }
}

public class Activity_Logs
{
    public string data { get; set; }
}

public class DataRoot
{
    public long board_id { get; set; }
    public string group_id { get; set; }
    public bool is_top_group { get; set; }
    public long pulse_id { get; set; }
    public string pulse_name { get; set; }
    public string column_id { get; set; }
    public string column_type { get; set; }
    public string column_title { get; set; }
    public Value value { get; set; }
    public Previous_Value previous_value { get; set; }
    public bool is_column_with_hide_permissions { get; set; }
    public string previous_textual_value { get; set; }
}

public class Value
{
    public Column_Settings column_settings { get; set; }
}

public class Column_Settings
{
    public bool includePulseInSubject { get; set; }
    public bool ccPulse { get; set; }
    public string bccList { get; set; }
}

public class Previous_Value
{
    public string email { get; set; }
    public string text { get; set; }
    public DateTime changed_at { get; set; }
    public Column_Settings1 column_settings { get; set; }
}

public class Column_Settings1
{
    public bool includePulseInSubject { get; set; }
    public bool ccPulse { get; set; }
    public string bccList { get; set; }
}

Then load the JSON and manipulate as follows,

var json = File.ReadAllText("data.json");
var rootLogs = JsonConvert.DeserializeObject<LogsRoot>(json);

Dictionary<string, string> fields = new Dictionary<string, string>();

foreach (var logJson in rootLogs.activity_logs)
{
    var log = JsonConvert.DeserializeObject<DataRoot>(logJson.data);
    fields.Add(log.column_id, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
    fields.Add(log.pulse_name, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
    fields.Add(log.previous_value.email, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
    fields.Add(log.previous_textual_value, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
}
吾性傲以野 2025-01-16 13:18:53

这可能无法解决您的所有问题,但对于您遇到的特定异常,这是因为您试图反序列化 JObject 而不是字符串。

也许你只是想要:

dynamic values = JsonConvert.DeserializeObject(update.Value.ToString());

This might not solve all your issues, but for the specific exception you are running into, it is because you are trying to deserialize a JObject instead of string.

Probably you just want:

dynamic values = JsonConvert.DeserializeObject(update.Value.ToString());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文