1

I'm new and just learning parsing with JSON

I'm checking if value exists in the array. my code is worked but I just wanna ask the shortest code or improvement for this?

this is what I'm getting: m3u8 It's randomely exists from array [0] to [4]. so I tried .contains method.

  public static async Task<string> GetInfoAsync(string url)
    {
        var resource = await GetWebSourceAsync(url);
        JObject jObject = JObject.Parse(resource);

        var m3u8 = string.Empty;

        if (jObject["data"]["program"]["video"][0].Value<string>().Contains("#EXTM3U"))
        {
            m3u8 = jObject["data"]["program"]["video"][0]["m3u8"].Value<string>();
        }
        else if (jObject["data"]["program"]["video"][1].Value<string>().Contains("#EXTM3U"))
        {
            m3u8 = jObject["data"]["program"]["video"][1]["m3u8"].Value<string>();
        }
        else if (jObject["data"]["program"]["video"][2].Value<string>().Contains("#EXTM3U"))
        {
            m3u8 = jObject["data"]["program"]["video"][2]["m3u8"].Value<string>();
        }
        else if (jObject["data"]["program"]["video"][3].Value<string>().Contains("#EXTM3U"))
        {
            m3u8 = jObject["data"]["program"]["video"][3]["m3u8"].Value<string>();
        }
        else if (jObject["data"]["program"]["video"][4].Value<string>().Contains("#EXTM3U"))
        {
            m3u8 = jObject["data"]["program"]["video"][4]["m3u8"].Value<string>();
        }

        return m3u8;
    }

Here's the structures of JSON

2
  • Does what you are parsing have a regular schema? If so, create a set of C# classes and parse the data into a graph of objects. Walking through a set of strongly typed objects would be faster than what you are doing Commented Jul 11, 2020 at 15:09
  • Ahm what do you mean regular schema? Commented Jul 11, 2020 at 15:10

3 Answers 3

2

You could use LINQ to your advantage:

JObject jObject = new JObject();
var m3u = jObject["data"]["program"]["video"]
    .Where(i => i.Value<string>().Contains("#EXTM3U"))
    .FirstOrDefault()
    ?["m3u8"].Value<string>();

Let me know if it doesn't help.

Sign up to request clarification or add additional context in comments.

5 Comments

It says: Cannot cast Newtonsoft.Json.Linq.JObject to Newtonsoft.Json.Linq.JToken.'
Alright I got it. it worked. I'll post the solution
Yeah. it's also helped me for the subtitle. Because the subtitle are different Language with random object as well :)
I guess you can improve the code by merging Where and FirstOrDefault by writing predicate of 'Where' into 'FirstOrDefault'. IntelliSense should suggest it for you.
Oh I see. but the subtitle I talked about is not in the "video" Object it's from ["data"]["program"]["stl"]
2

Assuming your json text be similar to (it may have much more data, it does not matter):

{
    "data": {
        "program": {
            "video": [
                {
                    "m3u8Url": "http://go.to/video1",
                    "vid": "",
                    "rp": 0 
                },
                {
                    "m3u8Url": "http://go.to/video2",
                    "m3u8": "#EXTM3U #EXT-X-TARGET...",
                    "vid": "",
                    "rp": 0
                },
                {
                    "m3u8Url": "http://go.to/video3",
                    "vid": "",
                    "rp": 0
                }
            ]
        }
    }
}

You can retrieve the first video containing #EXTM3U using the following code:

var anonymousObj = new
{
    data = new
    {
        program = new
        {
            video = new[]
            {
                new
                {
                    m3u8Url = "",
                    m3u8 = "",
                    vid = "",
                    rp = 0
                }
            }
        }
    }
};
var obj = JsonConvert.DeserializeAnonymousType(json, anonymousObj);
var video = obj?.data?.program?.video?.FirstOrDefault(v => v.m3u8?.Contains("#EXTM3U") == true);

Other solution, if you're using visual studio, you can map any JSON text to class using the editor. Go to Edit -> Paste Special -> Paste JSON as Classes. The output for example JSON will be:

public class Rootobject
{
    public Data data { get; set; }
}

public class Data
{
    public Program program { get; set; }
}

public class Program
{
    public Video[] video { get; set; }
}

public class Video
{
    public string m3u8Url { get; set; }
    public string vid { get; set; }
    public int rp { get; set; }
    public string m3u8 { get; set; }
    //it will have other props
}

Then you can use the JsonConvert and deserialize to Rootobject type.

var obj2 = JsonConvert.DeserializeObject<Rootobject>(json);
var video2 = obj2?.data?.program?.video?.FirstOrDefault(v => v.m3u8?.Contains("#EXTM3U") == true);

11 Comments

Thank you for this explanation. I'm currently trying it :) Yes it's the same structure Like this. only the changes is the position of the value "#EXTM3U" i.imgur.com/ygkiGsg.jpg
Its a bit different, video is an object... you need to make small changes to make it work.
To update the answer, please attach an image to see any node with #EXTM3U inside.
Yeah @dbvega it's an object. That's what I'm trying to say It's randomely exists from object [0] to [4]. by the way I tried your code so maybe I have to find out how to use it for the object I got this error: Unexpected character encountered while parsing value: {. Path 'data
I just see the image, now I figured out where is #EXTM3U... I will update my answer.
|
0

Alright this is the solution by @Volodymyr Thank you so much.

  public static async Task<string> GetInfoAsync(string url, EpisodeInfo info)
    {
        var resource = await GetWebSourceAsync(url);

        JObject jObject = JObject.Parse(resource);
        return jObject["data"]["program"]["video"]
            .Where(i => i.ToString().Contains("#EXTM3U"))
            .FirstOrDefault()
            ?["m3u8"].ToString();
    }

and Here's the solution by @dbvega Thanks too.

   public static async Task<string> GetWebSourceAsync(string url)
    {
        var handler = new HttpClientHandler
        {
            Proxy = null,
            UseProxy = false
        };

        using (var client = new HttpClient(handler))
        {
            client.DefaultRequestHeaders.Add("Method", "GET");
            client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36");

            using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
            {
                response.EnsureSuccessStatusCode();
                string json = await response.Content.ReadAsStringAsync();
                var obj = JsonConvert.DeserializeObject<Rootobject>(json);
                var result = obj?.data?.program?.video?.FirstOrDefault(v => v.m3u8?.Contains("#EXTM3U") == true);
                return JsonConvert.SerializeObject(result, Newtonsoft.Json.Formatting.Indented);
            }
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.