1

I get this Json string from the Channel Points Event from the Twitch Pubsub System.

{
"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"
    }
  }
}

And I want to convert this string into following variables: Edit: I updated these Clases with 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; }
    }

I tried different methodes to deseralize a Json string but nothing realy worked. My last attempt was following: (edited)

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

I would be very thankful if someone could help me :)

Test String:

{"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\"}}}"}}
MP9
  • 33
  • 4
  • 1
    Are you getting Any error? What error? You need to use https://json2csharp.com/ to create c# classes for the json you have. – Chetan Ranpariya Jan 04 '21 at 13:03
  • @ChetanRanpariya Unfortunetly there is no error. – MP9 Jan 04 '21 at 13:11
  • Then what's then issue you are facing? You have catch block with no code so even if there is an exception thrown it is silently gulped and you never know if the exception occurred. – Chetan Ranpariya Jan 04 '21 at 13:11
  • @ChetanRanpariya I tried the solution from json2csharp.com but it still wont work. – MP9 Jan 04 '21 at 13:12
  • 3
    `wont work` does not explain any thing about the issue you are facing – Chetan Ranpariya Jan 04 '21 at 13:13
  • What version of .NET are you using? Try using either `Json.NET` or `System.Text.Json` instead of `JavaScriptSerializer`. – Guru Stron Jan 04 '21 at 13:14
  • @ChetanRanpariya System.NullReferenceException is the exeption that I get, but this is simly because i want to Display a veriable in my Console but Json converter doesn't do anything. – MP9 Jan 04 '21 at 13:18
  • @GuruStron I thried the JavaScriptSerializer at first but now i'm trying the Newtonsoft.Json.JsonConvert. – MP9 Jan 04 '21 at 13:20
  • I'm Using .NET Framework 4.7.1 – MP9 Jan 04 '21 at 13:21
  • When you used https://json2csharp.com/ , did it generate different set of classes? – Chetan Ranpariya Jan 04 '21 at 13:23
  • @ChetanRanpariya yeah it did generate a different set of classes. I updated my question with my latest try to solve this. – MP9 Jan 04 '21 at 13:26
  • I created classes using json2csharp.com and used the same JSON text as you and I see `hit a gleesh walk on stream` as output in console. – Chetan Ranpariya Jan 04 '21 at 13:28
  • @ChetanRanpariya what do you mean? :D – MP9 Jan 04 '21 at 13:31
  • I mean your code, works fine with your JSON and the classes you have shared in question.. https://dotnetfiddle.net/J8IebH – Chetan Ranpariya Jan 04 '21 at 13:33
  • @ChetanRanpariya will it still work if you try it with the string i added to my question instead? – MP9 Jan 04 '21 at 13:38
  • 1
    it is the same string.. .you can check https://dotnetfiddle.net/Lm8MSy.. Did you debug your code and check if `e` is not null and `e.Data` is not null? – Chetan Ranpariya Jan 04 '21 at 13:39
  • @ChetanRanpariya e and e.Data are both not null. Everytime I try it i get the System.NullReferenceException. – MP9 Jan 04 '21 at 13:44
  • The testString you shared is the value of `e.Data`? What is the type of `e.Data`? Shouldn't you be doing `var json = e.Data.Message`? – Chetan Ranpariya Jan 04 '21 at 13:45
  • @ChetanRanpariya e.Data is already a string. – MP9 Jan 04 '21 at 13:47
  • Use the debugger.. it will tell you which variable is null. – Jawad Jan 04 '21 at 13:51
  • @Jawad not realy :/ the variable is null because the Json converter doesn't do what its supposed to. – MP9 Jan 04 '21 at 13:52
  • @ChetanRanpariya how does the dotnetfiddle work? Have you tried it with the string i provided in the last row of my question? – MP9 Jan 04 '21 at 13:53
  • you need to explain the issue with the real input data you are dealing with. the JSON you shared in start is not the same as the test string you shared later. you can go thru the answer posted below to solve your issues.. A nicely written question helps solving the problem faster. – Chetan Ranpariya Jan 04 '21 at 14:08

1 Answers1

1

There are many things unclear in the question to start with. The issue was not clear, the input data and the expectations were not explained properly.

At the later stage it is revealed that the JSON shared in the question is not value coming out of e.Data.

Anyways, moving to solving the real problem.

e.Data itself is a JSON string and it has one child property which in-turn is a JSON string.

Hence, two fold JSON desrialization is required.

Following classes you need for the first level of deserialization.

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

the string of e.Data represents the JSON structure of DataRoot class. So you need to first deserialize DataRoot object as following.

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

Now the next JSON (which is shared first in the question) is available inside rootData.data.message property. To deserialize it, you need following 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 represents the JSON structure of Root class declared above. So you need to deserialize it as following.

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

So the final version of the code will look like following.

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

I hope this will help you resolve your issue.

Chetan Ranpariya
  • 5,895
  • 3
  • 16
  • 27
  • I realised a few moment befor I read your solution that the Date from e.Data is completely different than the data that is in the documentation. Thank you very very much for your time. It works now! :) – MP9 Jan 04 '21 at 14:16