在 C# 中反序列化一个复杂的 JSON,Twitch Pubsub
Deserialize a complex JSON in C#, Twitch Pubsub
的 Channel Points 事件中得到这个 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",
"channel_id": "30515034",
"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
更新了这些 Clases
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 Framework 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\",\"channel_id\":\"196174120\",\"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 字符串并且它有一个 child 属性 其中 in-turn 是一个 JSON 字符串。
因此,需要进行两次 JSON 反序列化。
第一级反序列化需要以下 classes。
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
class的JSON结构。所以你需要先反序列化 DataRoot object 如下。
var rootData = JsonConvert.DeserializeObject<DataRoot>(e.Data);
现在下一个 JSON(在问题中首先共享)在 rootData.data.message
属性 中可用。要反序列化它,您需要遵循 classes.
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
class的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);
}
}
希望本文能帮助您解决问题。
{
"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",
"channel_id": "30515034",
"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
更新了这些 Clasespublic 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 Framework 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\",\"channel_id\":\"196174120\",\"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 字符串并且它有一个 child 属性 其中 in-turn 是一个 JSON 字符串。
因此,需要进行两次 JSON 反序列化。
第一级反序列化需要以下 classes。
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
class的JSON结构。所以你需要先反序列化 DataRoot object 如下。
var rootData = JsonConvert.DeserializeObject<DataRoot>(e.Data);
现在下一个 JSON(在问题中首先共享)在 rootData.data.message
属性 中可用。要反序列化它,您需要遵循 classes.
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
class的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);
}
}
希望本文能帮助您解决问题。