在 C#、Twitch Pubsub 中反序列化复杂的 JSON

如何解决在 C#、Twitch Pubsub 中反序列化复杂的 JSON

我从 Twitch Pubsub System 的 Channel Points Event 中得到了这个 Json 字符串。

{
"type": "reward-redeemed","data": {
  "timestamp": "2019-11-12T01:29:34.98329743Z","redemption": {
    "id": "9203c6f0-51b6-4d1d-a9ae-8eafdb0d6d47","user": {
      "id": "30515034","login": "davethecust","display_name": "davethecust"
    },"channel_id": "30515034","redeemed_at": "2019-12-11T18:52:53.128421623Z","reward": {
      "id": "6ef17bb2-e5ae-432e-8b3f-5ac4dd774668","title": "hit a gleesh walk on stream","prompt": "cleanside's finest \n","cost": 10,"is_user_input_required": true,"is_sub_only": false,"image": {
        "url_1x": "https://static-cdn.jtvnw.net/custom-reward-images/30515034/6ef17bb2-e5ae-432e-8b3f-5ac4dd774668/7bcd9ca8-da17-42c9-800a-2f08832e5d4b/custom-1.png","url_2x": "https://static-cdn.jtvnw.net/custom-reward-images/30515034/6ef17bb2-e5ae-432e-8b3f-5ac4dd774668/7bcd9ca8-da17-42c9-800a-2f08832e5d4b/custom-2.png","url_4x": "https://static-cdn.jtvnw.net/custom-reward-images/30515034/6ef17bb2-e5ae-432e-8b3f-5ac4dd774668/7bcd9ca8-da17-42c9-800a-2f08832e5d4b/custom-4.png"
      },"default_image": {
        "url_1x": "https://static-cdn.jtvnw.net/custom-reward-images/default-1.png","url_2x": "https://static-cdn.jtvnw.net/custom-reward-images/default-2.png","url_4x": "https://static-cdn.jtvnw.net/custom-reward-images/default-4.png"
      },"background_color": "#00C7AC","is_enabled": true,"is_paused": false,"is_in_stock": true,"max_per_stream": { "is_enabled": false,"max_per_stream": 0 },"should_redemptions_skip_request_queue": true
    },"user_input": "yeooo","status": "FULFILLED"
    }
  }
}

我想将此字符串转换为以下变量: 编辑:我用 Json2CSharp.com 更新了这些类

public class User
    {
        public string id { get; set; }
        public string login { get; set; }
        public string display_name { get; set; }
    }

    public class Image
    {
        public string url_1x { get; set; }
        public string url_2x { get; set; }
        public string url_4x { get; set; }
    }

    public class DefaultImage
    {
        public string url_1x { get; set; }
        public string url_2x { get; set; }
        public string url_4x { get; set; }
    }

    public class MaxPerStream
    {
        public bool is_enabled { get; set; }
        public int max_per_stream { get; set; }
    }

    public class Reward
    {
        public string id { get; set; }
        public string channel_id { get; set; }
        public string title { get; set; }
        public string prompt { get; set; }
        public int cost { get; set; }
        public bool is_user_input_required { get; set; }
        public bool is_sub_only { get; set; }
        public Image image { get; set; }
        public DefaultImage default_image { get; set; }
        public string background_color { get; set; }
        public bool is_enabled { get; set; }
        public bool is_paused { get; set; }
        public bool is_in_stock { get; set; }
        public MaxPerStream max_per_stream { get; set; }
        public bool should_redemptions_skip_request_queue { get; set; }
    }

    public class Redemption
    {
        public string id { get; set; }
        public User user { get; set; }
        public string channel_id { get; set; }
        public string redeemed_at { get; set; }
        public Reward reward { get; set; }
        public string user_input { get; set; }
        public string status { get; set; }
    }

    public class Data
    {
        public string timestamp { get; set; }
        public Redemption redemption { get; set; }
    }

    public class Root
    {
        public string type { get; set; }
        public Data data { get; set; }
    }

我尝试了不同的方法来反序列化 Json 字符串,但没有任何效果。 我的最后一次尝试如下:(已编辑)

private static void SocketMessage(object sender,MessageEventArgs e)
        {
            try
            {
                Console.WriteLine(e.Data);
                //string json = e.Data.Replace("\"{","{").Replace("\\",string.Empty);
                string json = e.Data;
                Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(json);
                Console.WriteLine(myDeserializedClass.data.redemption.reward.title);
            }
            catch(Exception ex)
            {
                Console.Write(ex);
            }
        }

.NET 框架 4.7.1

如果有人能帮助我,我将不胜感激:)

测试字符串:

{"type":"MESSAGE","data":{"topic":"channel-points-channel-v1.196174120","message":"{\"type\":\"reward-redeemed\",\"data\":{\"timestamp\":\"2021-01-04T13:36:47.746629895Z\",\"redemption\":{\"id\":\"c664b1d8-65a6-4fb9-bef0-7b90a5a3819d\",\"user\":{\"id\":\"196174120\",\"login\":\"p90ez\",\"display_name\":\"P90Ez\"},\"channel_id\":\"196174120\",\"redeemed_at\":\"2021-01-04T13:36:47.746629895Z\",\"reward\":{\"id\":\"0452f6cb-cb1c-4c8e-9978-7103d01b621a\",\"title\":\"Willkommenssound\",\"prompt\":\"Du erhälst deinen eigenen Command mit einem Sound deiner Wahl (bitte mir den Link auf Discord etc. schicken)! Für non-Subs max 15 Sekunden,für Subs bis zu 30 Sekunden.\\n(geklaut von PrideGaymer)\",\"cost\":15000,\"is_user_input_required\":false,\"is_sub_only\":false,\"image\":{\"url_1x\":\"https://static-cdn.jtvnw.net/custom-reward-images/196174120/0452f6cb-cb1c-4c8e-9978-7103d01b621a/3feba875-7151-45e8-8bf1-09d78e48baf1/custom-1.png\",\"url_2x\":\"https://static-cdn.jtvnw.net/custom-reward-images/196174120/0452f6cb-cb1c-4c8e-9978-7103d01b621a/3feba875-7151-45e8-8bf1-09d78e48baf1/custom-2.png\",\"url_4x\":\"https://static-cdn.jtvnw.net/custom-reward-images/196174120/0452f6cb-cb1c-4c8e-9978-7103d01b621a/3feba875-7151-45e8-8bf1-09d78e48baf1/custom-4.png\"},\"default_image\":{\"url_1x\":\"https://static-cdn.jtvnw.net/custom-reward-images/default-1.png\",\"url_2x\":\"https://static-cdn.jtvnw.net/custom-reward-images/default-2.png\",\"url_4x\":\"https://static-cdn.jtvnw.net/custom-reward-images/default-4.png\"},\"background_color\":\"#FF9138\",\"is_enabled\":true,\"is_paused\":false,\"is_in_stock\":true,\"max_per_stream\":{\"is_enabled\":false,\"max_per_stream\":0},\"should_redemptions_skip_request_queue\":true,\"template_id\":null,\"updated_for_indicator_at\":\"2020-02-04T23:20:28.600840418Z\",\"max_per_user_per_stream\":{\"is_enabled\":false,\"max_per_user_per_stream\":0},\"global_cooldown\":{\"is_enabled\":false,\"global_cooldown_seconds\":0},\"redemptions_redeemed_current_stream\":null,\"cooldown_expires_at\":null},\"status\":\"FULFILLED\"}}}"}}

解决方法

这个问题有很多不清楚的地方。 问题不明确,输入数据和期望没有正确解释。

后期发现问题中共享的 JSON 不是 e.Data 中的值。

无论如何,开始解决真正的问题。

e.Data 本身是一个 JSON 字符串,它有一个子属性,而该属性又是一个 JSON 字符串。

因此,需要两次 JSON 反序列化。

第一级反序列化所需的以下类。

public class MessageData
{
    public string topic { get; set; }
    public string message { get; set; }
}

public class DataRoot
{
    public string type { get; set; }
    public MessageData data { get; set; }
}

e.Data 的字符串表示 DataRoot 类的 JSON 结构。所以你需要首先反序列化 DataRoot 对象,如下所示。

var rootData = JsonConvert.DeserializeObject<DataRoot>(e.Data);

现在下一个 JSON(在问题中首先共享)在 rootData.data.message 属性中可用。要反序列化它,您需要以下类。

public class User
{
    public string id { get; set; }
    public string login { get; set; }
    public string display_name { get; set; }
}

public class Image
{
    public string url_1x { get; set; }
    public string url_2x { get; set; }
    public string url_4x { get; set; }
}

public class DefaultImage
{
    public string url_1x { get; set; }
    public string url_2x { get; set; }
    public string url_4x { get; set; }
}

public class MaxPerStream
{
    public bool is_enabled { get; set; }
    public int max_per_stream { get; set; }
}

public class Reward
{
    public string id { get; set; }
    public string channel_id { get; set; }
    public string title { get; set; }
    public string prompt { get; set; }
    public int cost { get; set; }
    public bool is_user_input_required { get; set; }
    public bool is_sub_only { get; set; }
    public Image image { get; set; }
    public DefaultImage default_image { get; set; }
    public string background_color { get; set; }
    public bool is_enabled { get; set; }
    public bool is_paused { get; set; }
    public bool is_in_stock { get; set; }
    public MaxPerStream max_per_stream { get; set; }
    public bool should_redemptions_skip_request_queue { get; set; }
}

public class Redemption
{
    public string id { get; set; }
    public User user { get; set; }
    public string channel_id { get; set; }
    public string redeemed_at { get; set; }
    public Reward reward { get; set; }
    public string user_input { get; set; }
    public string status { get; set; }
}

public class Data
{
    public string timestamp { get; set; }
    public Redemption redemption { get; set; }
}

public class Root
{
    public string type { get; set; }
    public Data data { get; set; }
}

rootData.data.message 表示上面声明的 Root 类的 JSON 结构。所以你需要反序列化它如下。

var json = rootData.data.message;
var myDeserializedClass = JsonConvert.DeserializeObject<Root>(json);

所以代码的最终版本将如下所示。

private static void SocketMessage(object sender,MessageEventArgs e)
{
    try
    {
        var rootData = JsonConvert.DeserializeObject<DataRoot>(e.Data);

        var json = rootData.data.message;

        Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(json);
        Console.WriteLine(myDeserializedClass.data.redemption.reward.title);
    }
    catch(Exception ex)
    {
        Console.Write(ex);
    }
}

希望这能帮助您解决问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res