Link to home
Start Free TrialLog in
Avatar of Wayne Barron
Wayne BarronFlag for United States of America

asked on

vb.net Deserialize JSON output - YouTube API (With somewhat of a working example included)

Hello All;

I had another thread open, but I closed it out and started this one.
With a working example, but need to get all the values, instead of a single value duplicated for the number of records returned.

Here is the test JSON that I am using.
{
 "kind": "youtube#playlistItemListResponse",
 "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/YJYLWeQ7ZaYKr3ce1Z9EIjD9WVU\"",
 "nextPageToken": "CAUQAA",
 "pageInfo": {
  "totalResults": 10,
  "resultsPerPage": 5
 },
 "items": [
  {
   "kind": "youtube#playlistItem",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/0TyxpFnbR5GigaSoRo2gAPfUHwE\"",
   "id": "UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay41NkI0NEY2RDEwNTU3Q0M2",
   "snippet": {
    "publishedAt": "2014-12-10T21:16:39.000Z",
    "channelId": "UCVUx0VcNxnHx7ZjuZK5Sthw",
    "title": "Private video",
    "description": "This video is private.",
    "channelTitle": "Late Show with David Letterman",
    "playlistId": "PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk",
    "position": 0,
    "resourceId": {
     "kind": "youtube#video",
     "videoId": "4bVgilYncao"
    }
   }
  },
  {
   "kind": "youtube#playlistItem",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/PVF3VoVEG0X1jmV6GeUNhpCIzF4\"",
   "id": "UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4yODlGNEE0NkRGMEEzMEQy",
   "snippet": {
    "publishedAt": "2014-12-10T21:16:58.000Z",
    "channelId": "UCVUx0VcNxnHx7ZjuZK5Sthw",
    "title": "Private video",
    "description": "This video is private.",
    "channelTitle": "Late Show with David Letterman",
    "playlistId": "PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk",
    "position": 1,
    "resourceId": {
     "kind": "youtube#video",
     "videoId": "H9eYkpgeeI8"
    }
   }
  },
  {
   "kind": "youtube#playlistItem",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/BLUJWU0eHjBeEizXySdnzUhi2lQ\"",
   "id": "UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4wMTcyMDhGQUE4NTIzM0Y5",
   "snippet": {
    "publishedAt": "2014-12-10T21:17:14.000Z",
    "channelId": "UCVUx0VcNxnHx7ZjuZK5Sthw",
    "title": "Private video",
    "description": "This video is private.",
    "channelTitle": "Late Show with David Letterman",
    "playlistId": "PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk",
    "position": 2,
    "resourceId": {
     "kind": "youtube#video",
     "videoId": "ONgN2Hgz3XE"
    }
   }
  },
  {
   "kind": "youtube#playlistItem",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/qlX2iXH1WPg7D3-eq7jInjQyj2c\"",
   "id": "UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay41MjE1MkI0OTQ2QzJGNzNG",
   "snippet": {
    "publishedAt": "2014-12-10T21:17:30.000Z",
    "channelId": "UCVUx0VcNxnHx7ZjuZK5Sthw",
    "title": "Private video",
    "description": "This video is private.",
    "channelTitle": "Late Show with David Letterman",
    "playlistId": "PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk",
    "position": 3,
    "resourceId": {
     "kind": "youtube#video",
     "videoId": "1Ee4bfu_t3c"
    }
   }
  },
  {
   "kind": "youtube#playlistItem",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/698H3tj04Cx7lZ8z4rHjL4DPtUI\"",
   "id": "UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4wOTA3OTZBNzVEMTUzOTMy",
   "snippet": {
    "publishedAt": "2014-12-10T21:17:47.000Z",
    "channelId": "UCVUx0VcNxnHx7ZjuZK5Sthw",
    "title": "Private video",
    "description": "This video is private.",
    "channelTitle": "Late Show with David Letterman",
    "playlistId": "PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk",
    "position": 4,
    "resourceId": {
     "kind": "youtube#video",
     "videoId": "Bzr5VtFvSyw"
    }
   }
  }
 ]
}

Open in new window


OR (You can use the code below if you have a YouTube API to add to the end of the URL String.)


This is the working code that returns duplicate values.

' Newtonsoft.Json
Dim n As New WebClient()
        Dim jsonString As String = n.DownloadString("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2C+id&playlistId=PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk&key=YOUR_API_KEY_HERE")

        Dim jo = Newtonsoft.Json.Linq.JObject.Parse(jsonString)
        Dim VidID = jo("items")(0)("snippet")("resourceId")("videoId")
        For Each Row In jo("items") 
            Response.Write(VidID)
        Next

Open in new window


Could someone please assist me in deserialize this?
Thank You
Carrzkiss
Avatar of Ryan Chong
Ryan Chong
Flag of Singapore image

it seems that you're working well in progress :)

With a working example, but need to get all the values, instead of a single value duplicated for the number of records returned.
what info you wish to get here? or you want to deserialize the whole JSON string to object?
SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Wayne Barron

ASKER

@Ryan
It is a two step process.
The example that I provided, cannot be used as it is PRIVATE.

Step #1: [Get the videoId]
Process playlist, and get all VideoId's associated with that list.


Step #2: [Get the information]
Use the videoId to get the information about the Video.
(This is from one of my Video's as an Example)
{
 "items": [
  {
   "id": "7Ms3vgQA6yg",
   "snippet": {
    "channelId": "UCwrBbNtAINY8W2PGNQlSuZw",
    "title": "Visual studio 2010 - vb.net Lesson #4 - Insert data into Access Database",
    "categoryId": "27"
   },
   "statistics": {
    "viewCount": "4",
    "likeCount": "0",
    "dislikeCount": "0",
    "favoriteCount": "0",
    "commentCount": "0"
   }
  }
 ]
}

Open in new window


I can then parse this out to work in my news site.

The way the OLD API worked, I was some-what able to do this in one step.
However, that is no longer the case with the new API.

@it_saige
I have played around with code similar to yours, but never found out how to properly use it.
I will take a deeper look at yours, and see if I can make it work the way I need it to.

Wayne
@it_saige

How would I use your code in a web page?
This seems to be for an App.
I figured out how to use it.
Just trying to Figure out how to use it for my needs.
@it_saige

Question about your code.
I am messing around inside of the [ return string.format()]
I have selected the items that I want to keep and discarded the ones that I do not need.


To insert these values into a database. Would I place the database "INSERT" statement inside of the [Class Snippet]
(or)
Would it be placed after the DIM Playlist?
To insert or update the values in a database, it actually makes more sense to use AddWithValue.

So this would look something like (untested):
Private Sub InsertPlayList(ByVal playList As PlayList)
    Dim playListId = -1
    Dim pageInfoId = -1
    Dim snippetId = -1
    Dim resourceId = -1
    Using connection = New SqlConnection("yourconnectionstring")
        Using command = New SqlCommand("INSERT INTO dbo.PageInfo (TOTALRESULTS,RESULTSPERPAGE) VALUES (@TOTALRESULTS,@RESULTSPERPAGE)", connection)
            command.Parameters.AddWithValue("@TOTALRESULTS", playList.PageInfo.TotalResults)
            command.Parameters.AddWithValue("@RESULTSPERPAGE", playList.PageInfo.ResultsPerPage)
            pageInfoId = CType(command.ExecuteScalar(), Integer)
        End Using

        Using command = New SqlCommand("INSERT INTO dbo.PlayList (KIND,ETAG,NEXTPAGETOKEN,PAGEINFOID) VALUES (@KIND,@ETAG,@NEXTPAGETOKEN,@PAGEINFOID)", connection)
            command.Parameters.AddWithValue("@KIND", playList.Kind)
            command.Parameters.AddWithValue("@ETAG", playList.ETag)
            command.Parameters.AddWithValue("@NETPAGETOKEN", playList.NextPageToken)
            command.Parameters.AddWithValue("@PAGEINFOID", pageInfoId)
            playListId = CType(command.ExecuteScalar(), Integer)
        End Using

        For Each [item] In playList.Items
            Using command = New SqlCommand("INSERT INTO dbo.ResourceID (KIND,VIDEOID) VALUES (@KIND,@VIDEOID)", connection)
                command.Parameters.AddWithValue("@KIND", item.Snippet.ResourceId.Kind)
                command.Parameters.AddWithValue("@VIDEOID", item.Snippet.ResourceId.VideoId)
                resourceId = CType(command.ExecuteScalar(), Integer)
            End Using

            Using command = New SqlCommand("INSERT INTO dbo.Snippet (PUBLISHEDAT,CHANNELID,TITLE,DESCRIPTION,CHANNELTITLE,PLAYLISTID,POSITION,RESOURCEID) VALUES (@PUBLISHEDAT,@CHANNELID,@TITLE,@DESCRIPTION,@CHANNELTITLE,@PLAYLISTID,@POSITION,@RESOURCEID)", connection)
                command.Parameters.AddWithValue("@PUBLISHEDAT", item.Snippet.PublishedAt)
                command.Parameters.AddWithValue("@CHANNELID", item.Snippet.ChannelId)
                command.Parameters.AddWithValue("@TITLE", item.Snippet.Title)
                command.Parameters.AddWithValue("@DESCRIPTION", item.Snippet.Description)
                command.Parameters.AddWithValue("@CHANNELTITLE", item.Snippet.ChannelTitle)
                command.Parameters.AddWithValue("@PLAYLISTID", item.Snippet.PlayListId)
                command.Parameters.AddWithValue("@POSITION", item.Snippet.Position)
                command.Parameters.AddWithValue("@RESOURCEID", resourceId)
                snippetId = CType(command.ExecuteScalar(), Integer)
            End Using

            Using command = New SqlCommand("INSERT INTO dbo.Item (PLAYLISTID,KIND,ETAG,ID,SNIPPETID) VALUES (@PLAYLISTID,@KIND,@ETAG,@ID,@SNIPPETID)", connection)
                command.Parameters.AddWithValue("@PLAYLISTID", playListId)
                command.Parameters.AddWithValue("@KIND", [item].Kind)
                command.Parameters.AddWithValue("@ETAG", [item].ETag)
                command.Parameters.AddWithValue("@ID", [item].Id)
                command.Parameters.AddWithValue("@SNIPPETID", snippetId)
                command.ExecuteScalar()
            End Using
        Next
    End Using
End Sub

Open in new window

-saige-
Thank you, -saige-.
However, this would need to be in a single INSERT statement.
I will play around with what you have provided and see if I can come up with something, using your code as a building block.

This should be fun.
@saige

OK, I am trying to learn what you have done with the code, so I can use it to do other pages with, without having to ask a bunch of questions later on. Also, for those that come in here, they will also be able to learn from this as well.
Let me know if this is correct?

Kind: {1} = The 1 means there is only 1 object.
Items: {5} = There are 5 objects and the end of the first nodes.
The items are:
[            = 1
{            = 2
kind      = 3
etag      = 4
id           = 5

And then "snippet" starts its own Node set.
snippet
{                       = 1
publishedAt   = 2
channelId       = 3
title                  = 4
description     = 5

And then Thumbnail has its own Node set, and so on...

This has me a little off, on what it means.
>  {0}{1}{1}{1}VideoId: {3}

Is this correct, or am I off by a long shot?
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you, -saige-
When I am not still half-asleep, I will read back over what you wrote, and get a better understanding.
I want to thank you for taking the time to explain this as well.
Wayne
I LOVE the last solution that you provided.
It works SO Well!!!
It is less coding than the original, and much easier to maintain than the first code sample you provided.
I am Glad that I asked the question with the misunderstanding of the way you coded it.
As if it was not for my misunderstanding, of what you originally proposed, you would not have provided this excellent code example and explanation.

I am still not 100% on top of what you did in the first example, with all the numbers.
Though I am learning.
The last code you provided is much easier to work with.
Not certain if I will be able to do everything that I want with it, however. I will cross that bridge when I get there.

Thank you so much -saige- you have really helped me out a LOT.

Wayne
-saige-

I have run into a slight issue, and wonder if you can assist me.
This is taken from my channel.

{
 "nextPageToken": "CDMQAA",
 "prevPageToken": "CDIQAQ",
 "pageInfo": {
  "totalResults": 83,
  "resultsPerPage": 1
 },
 "items": [
  {
   "id": "PLoGpay6XnQnQPjBAntJCpVFzAFg-RwJ9S",
   "snippet": {
    "publishedAt": "2013-05-19T00:55:32.000Z",
    "channelId": "UC0crFgTrPx5t6YM2NumtFoA",
    "title": "Adobe Premiere",
    "description": "",
    "thumbnails": {
     "standard": {
      "url": "https://i.ytimg.com/vi/WJaT1vLKDPc/default.jpg"
     }
    },
    "channelTitle": "Dark Effects Studios"
   },
   "contentDetails": {
    "itemCount": 9
   }
  }
 ]
}

Open in new window

(I got the itemCount, that was simple)

What I am needing is the URL of the image.
 "url": "https://i.ytimg.com/vi/WJaT1vLKDPc/default.jpg"
However, I am having a difficult time getting it.

This is what I have tried.

      Class Snippet
        Public Property PublishedAt() As String
        Public Property ChannelId() As String
        Public Property Title() As String
        Public Property Description() As String
        Public Property ChannelTitle() As String
        Public Property PlayListId() As String
        Public Property Position() As Integer
        Public Property thumbnails() As thumbnails
    End Class


    Class thumbnails
        Public Property standard() As standard
    End Class

    Class standard
        Public Property url() As String
    End Class

Open in new window


and the line to get the information.

item.Snippet.thumbnails.standard.url

Open in new window


I receive the following error.
Object reference not set to an instance of an object.
The error that I am getting means that the value is NULL.

There is ONE item that is showing up without an URL.

You know how you have your Favorites list on YouTube?
That is the ones that are causing the issues.
So, it is caused by a record that does not exist.
In this case, it is my favorites.
SO. The question is.
How to bypass that list.

This the is Favorites.

{
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/hnhmasSCjJz0vBS08sQUDwgwTIQ\"",
   "id": "FL0crFgTrPx5t6YM2NumtFoA",
   "snippet": {
    "publishedAt": "2011-05-14T11:05:40.000Z",
    "channelId": "UC0crFgTrPx5t6YM2NumtFoA",
    "title": "Favorites",
    "description": "",
    "channelTitle": "Dark Effects Studios"
   },
   "contentDetails": {
    "itemCount": 6
   }
  }

Open in new window

You have to check each property to see if it is nothing before trying to access the properties underneath.  Newtonsoft will create a new instance of missing properties but if the internal Standard property is null (or nothing) then the Url will not exist; e.g. -
Imports System.Data.SqlClient

Module Module1
    Const json = "{" _
& """kind"": ""youtube#playlistItemListResponse"", " _
& """etag"" :  ""\""m2yskBQFythfE4irbTIeOgYYfBU/YJYLWeQ7ZaYKr3ce1Z9EIjD9WVU\"""", " _
& """nextPageToken"": ""CAUQAA"", " _
& """pageInfo"": {""totalResults"": 10,""resultsPerPage"": 5}, " _
& """items"": [" _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/0TyxpFnbR5GigaSoRo2gAPfUHwE\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay41NkI0NEY2RDEwNTU3Q0M2"",""snippet"": {""publishedAt"": ""2014-12-10T2116:39.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""thumbnails"": {""standard"": {""url"": ""https://i.ytimg.com/vi/WJaT1vLKDPc/default.jpg""}},""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 0,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""4bVgilYncao""}}}," _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/PVF3VoVEG0X1jmV6GeUNhpCIzF4\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4yODlGNEE0NkRGMEEzMEQy"",""snippet"": {""publishedAt"": ""2014-12-10T2116:58.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 1,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""H9eYkpgeeI8""}}}," _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/BLUJWU0eHjBeEizXySdnzUhi2lQ\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4wMTcyMDhGQUE4NTIzM0Y5"",""snippet"": {""publishedAt"": ""2014-12-10T2117:14.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""thumbnails"": {},""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 2,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""ONgN2Hgz3XE""}}}," _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/qlX2iXH1WPg7D3-eq7jInjQyj2c\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay41MjE1MkI0OTQ2QzJGNzNG"",""snippet"": {""publishedAt"": ""2014-12-10T2117:30.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""thumbnails"": {""standard"": {}},""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 3,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""1Ee4bfu_t3c""}}}," _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/698H3tj04Cx7lZ8z4rHjL4DPtUI\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4wOTA3OTZBNzVEMTUzOTMy"",""snippet"": {""publishedAt"": ""2014-12-10T2117:47.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""thumbnails"": {""standard"": {""url"": null }},""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 4,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""Bzr5VtFvSyw""}}}]}"

    Sub Main()
        Dim playList = Newtonsoft.Json.JsonConvert.DeserializeObject(Of PlayList)(json)
        Console.WriteLine("Kind: " & playList.Kind)
        Console.WriteLine("ETag: " & playList.ETag)
        Console.WriteLine("NextPageToken: " & playList.NextPageToken)
        Console.WriteLine("PageInfo:")
        Console.WriteLine(vbTab & "Total Results: " & playList.PageInfo.TotalResults)
        Console.WriteLine(vbTab & "ResultsPerPage: " & playList.PageInfo.ResultsPerPage)
        Console.WriteLine("Items:")
        For Each [item] In playList.Items
            Console.WriteLine(vbTab & "Kind: " & [item].Kind)
            Console.WriteLine(vbTab & "ETag: " & [item].ETag)
            Console.WriteLine(vbTab & "Id: " & [item].Id)
            Console.WriteLine(vbTab & "Snippet:")
            Console.WriteLine(vbTab & vbTab & "PublishedAt: " & [item].Snippet.PublishedAt)
            Console.WriteLine(vbTab & vbTab & "ChannelId: " & [item].Snippet.ChannelId)
            Console.WriteLine(vbTab & vbTab & "Description: " & [item].Snippet.Description)
            Console.WriteLine(vbTab & vbTab & "ChannelTitle: " & [item].Snippet.ChannelTitle)
            Console.WriteLine(vbTab & vbTab & "PlayListId: " & [item].Snippet.PlayListId)
            Console.WriteLine(vbTab & vbTab & "Position: " & [item].Snippet.Position)
            Console.WriteLine(vbTab & vbTab & "ResourceId:")
            Console.WriteLine(vbTab & vbTab & vbTab & "Kind: " & [item].Snippet.ResourceId.Kind)
            Console.WriteLine(vbTab & vbTab & vbTab & "VideoId: " & [item].Snippet.ResourceId.VideoId)
            If [item].Snippet.Thumbnails IsNot Nothing Then
                Console.WriteLine(vbTab & vbTab & "Thumbnails:")
                If [item].Snippet.Thumbnails.Standard IsNot Nothing Then
                    Console.WriteLine(vbTab & vbTab & vbTab & "Standard:")
                    If [item].Snippet.Thumbnails.Standard.Url IsNot Nothing Then
                        Console.WriteLine(vbTab & vbTab & vbTab & vbTab & "Url: " & [item].Snippet.Thumbnails.Standard.Url)
                    End If
                End If
            End If
            Console.WriteLine()
        Next
        Console.ReadLine()
    End Sub
End Module

Class PlayList
    Public Property Kind() As String
    Public Property ETag() As String
    Public Property NextPageToken() As String
    Public Property PageInfo() As PageInfo
    Public Property Items() As List(Of Item)
End Class

Class Item
    Public Property Kind() As String
    Public Property ETag() As String
    Public Property Id() As String
    Public Property Snippet() As Snippet
End Class

Class PageInfo
    Public Property TotalResults() As Integer
    Public Property ResultsPerPage() As Integer
End Class

Class Snippet
    Public Property PublishedAt() As String
    Public Property ChannelId() As String
    Public Property Title() As String
    Public Property Description() As String
    Public Property ChannelTitle() As String
    Public Property PlayListId() As String
    Public Property Position() As Integer
    Public Property ResourceId() As ResourceId
    Public Property Thumbnails() As Thumbnails
End Class

Class Thumbnails
    Public Property Standard() As Standard
End Class

Class Standard
    Public Property Url() As String
End Class

Class ResourceId
    Public Property Kind() As String
    Public Property VideoId() As String
End Class

Open in new window


Produces the following output -User generated image
That being said, you could always implement backing fields so that default values are set; e.g. -
Class PlayList
    Dim _kind As String = String.Empty
    Dim _eTag As String = String.Empty
    Dim _nextPageToken As String = String.Empty
    Dim _pageInfo As PageInfo = New PageInfo()
    Dim _items As List(Of Item) = New List(Of Item)()

    Property Kind() As String
        Get
            Return _kind
        End Get
        Set
            _kind = Value
        End Set
    End Property

    Property ETag() As String
        Get
            Return _eTag
        End Get
        Set
            _eTag = Value
        End Set
    End Property

    Property NextPageToken() As String
        Get
            Return _nextPageToken
        End Get
        Set
            _nextPageToken = Value
        End Set
    End Property

    Property PageInfo() As PageInfo
        Get
            Return _pageInfo
        End Get
        Set
            _pageInfo = Value
        End Set
    End Property

    Property Items() As List(Of Item)
        Get
            Return _items
        End Get
        Set
            _items = Value
        End Set
    End Property
End Class

Open in new window

VB.NET also allows for us to set the default value on the auto-implemented property itself (C# does not):
Class PlayList
    Public Property Kind() As String = String.Empty
    Public Property ETag() As String = String.Empty
    Public Property NextPageToken() As String = String.Empty
    Public Property PageInfo() As PageInfo = New PageInfo()
    Public Property Items() As List(Of Item) = New List(Of Item)()
End Class

Open in new window


Personally, I would use the backing field method as you can put validators on your setter.  In either case, with the above changes we can get rid of our Null checking and just print out as before.

Proof of concept -
Imports System.Data.SqlClient

Module Module1
    Const json = "{" _
& """kind"": ""youtube#playlistItemListResponse"", " _
& """etag"" :  ""\""m2yskBQFythfE4irbTIeOgYYfBU/YJYLWeQ7ZaYKr3ce1Z9EIjD9WVU\"""", " _
& """nextPageToken"": ""CAUQAA"", " _
& """pageInfo"": {""totalResults"": 10,""resultsPerPage"": 5}, " _
& """items"": [" _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/0TyxpFnbR5GigaSoRo2gAPfUHwE\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay41NkI0NEY2RDEwNTU3Q0M2"",""snippet"": {""publishedAt"": ""2014-12-10T2116:39.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""thumbnails"": {""standard"": {""url"": ""https://i.ytimg.com/vi/WJaT1vLKDPc/default.jpg""}},""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 0,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""4bVgilYncao""}}}," _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/PVF3VoVEG0X1jmV6GeUNhpCIzF4\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4yODlGNEE0NkRGMEEzMEQy"",""snippet"": {""publishedAt"": ""2014-12-10T2116:58.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 1,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""H9eYkpgeeI8""}}}," _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/BLUJWU0eHjBeEizXySdnzUhi2lQ\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4wMTcyMDhGQUE4NTIzM0Y5"",""snippet"": {""publishedAt"": ""2014-12-10T2117:14.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""thumbnails"": {},""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 2,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""ONgN2Hgz3XE""}}}," _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/qlX2iXH1WPg7D3-eq7jInjQyj2c\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay41MjE1MkI0OTQ2QzJGNzNG"",""snippet"": {""publishedAt"": ""2014-12-10T2117:30.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""thumbnails"": {""standard"": {}},""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 3,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""1Ee4bfu_t3c""}}}," _
& "{""kind"": ""youtube#playlistItem"",""etag"": ""\""m2yskBQFythfE4irbTIeOgYYfBU/698H3tj04Cx7lZ8z4rHjL4DPtUI\"""",""id"": ""UExDSkxpSjh1U0pyQ3B4d3o0bG1uejFOdnZGMlN6WGJoay4wOTA3OTZBNzVEMTUzOTMy"",""snippet"": {""publishedAt"": ""2014-12-10T2117:47.000Z"",""channelId"": ""UCVUx0VcNxnHx7ZjuZK5Sthw"",""title"": ""Private video"",""description"": ""This video Is private."",""thumbnails"": {""standard"": {""url"": null }},""channelTitle"": ""Late Show with David Letterman"",""playlistId"": ""PLCJLiJ8uSJrCpxwz4lmnz1NvvF2SzXbhk"",""position"": 4,""resourceId"": {""kind"": ""youtube#video"",""videoId"": ""Bzr5VtFvSyw""}}}]}"

    Sub Main()
        Dim playList = Newtonsoft.Json.JsonConvert.DeserializeObject(Of PlayList)(json)
        Console.WriteLine("Kind: " & playList.Kind)
        Console.WriteLine("ETag: " & playList.ETag)
        Console.WriteLine("NextPageToken: " & playList.NextPageToken)
        Console.WriteLine("PageInfo:")
        Console.WriteLine(vbTab & "Total Results: " & playList.PageInfo.TotalResults)
        Console.WriteLine(vbTab & "ResultsPerPage: " & playList.PageInfo.ResultsPerPage)
        Console.WriteLine("Items:")
        For Each [item] In playList.Items
            Console.WriteLine(vbTab & "Kind: " & [item].Kind)
            Console.WriteLine(vbTab & "ETag: " & [item].ETag)
            Console.WriteLine(vbTab & "Id: " & [item].Id)
            Console.WriteLine(vbTab & "Snippet:")
            Console.WriteLine(vbTab & vbTab & "PublishedAt: " & [item].Snippet.PublishedAt)
            Console.WriteLine(vbTab & vbTab & "ChannelId: " & [item].Snippet.ChannelId)
            Console.WriteLine(vbTab & vbTab & "Description: " & [item].Snippet.Description)
            Console.WriteLine(vbTab & vbTab & "ChannelTitle: " & [item].Snippet.ChannelTitle)
            Console.WriteLine(vbTab & vbTab & "PlayListId: " & [item].Snippet.PlayListId)
            Console.WriteLine(vbTab & vbTab & "Position: " & [item].Snippet.Position)
            Console.WriteLine(vbTab & vbTab & "ResourceId:")
            Console.WriteLine(vbTab & vbTab & vbTab & "Kind: " & [item].Snippet.ResourceId.Kind)
            Console.WriteLine(vbTab & vbTab & vbTab & "VideoId: " & [item].Snippet.ResourceId.VideoId)
            Console.WriteLine(vbTab & vbTab & "Thumbnails:")
            Console.WriteLine(vbTab & vbTab & vbTab & "Standard:")
            Console.WriteLine(vbTab & vbTab & vbTab & vbTab & "Url: " & [item].Snippet.Thumbnails.Standard.Url)
            Console.WriteLine()
        Next
        Console.ReadLine()
    End Sub
End Module

Class PlayList
    Public Property Kind() As String = String.Empty
    Public Property ETag() As String = String.Empty
    Public Property NextPageToken() As String = String.Empty
    Public Property PageInfo() As PageInfo = New PageInfo()
    Public Property Items() As List(Of Item) = New List(Of Item)()
End Class

Class Item
    Public Property Kind() As String = String.Empty
    Public Property ETag() As String = String.Empty
    Public Property Id() As String = String.Empty
    Public Property Snippet() As Snippet = New Snippet()
End Class

Class PageInfo
    Public Property TotalResults() As Integer = -1
    Public Property ResultsPerPage() As Integer = -1
End Class

Class Snippet
    Public Property PublishedAt() As String = String.Empty
    Public Property ChannelId() As String = String.Empty
    Public Property Title() As String = String.Empty
    Public Property Description() As String = String.Empty
    Public Property ChannelTitle() As String = String.Empty
    Public Property PlayListId() As String = String.Empty
    Public Property Position() As Integer = -1
    Public Property ResourceId() As ResourceId = New ResourceId()
    Public Property Thumbnails() As Thumbnails = New Thumbnails()
End Class

Class Thumbnails
    Public Property Standard() As Standard = New Standard()
End Class

Class Standard
    Public Property Url() As String = String.Empty
End Class

Class ResourceId
    Public Property Kind() As String = String.Empty
    Public Property VideoId() As String = String.Empty
End Class

Open in new window


Now produces the following output -User generated image
-saige-
I implemented the first one. The check for NULL.
I was getting 83 records inserted, but now only 80.
(Need to check my playlist and see if it is 80 or 82.
As I know the 83 one was the [Favorites]
So, what happened to the other 2?
And the playlist is 83, with [Favorites] being the 83rd one.
The others have a condition that should not exist. See below.)

I like the concept behind the last method, (untested on my end right now)
See, I do not want to enter anything into the database if it does not have the Thumbnail URL assigned to it.
that means that it is not a part of what the Producer has uploaded.

I did find an issue.
Though, this is something that I will most likely have to find out elsewhere unless you have experienced it, and can possibly give me some information on. (Let me know if I need to open another thread for this one.)

The following is Visual Studio and Sony Vegas. (Visual Studio did not get added to the database)

On Visual Studio, it does have a Thumbnail assigned to it, but it seems to be all messed up in its coding.
"channelTitle": "Dark Effects Studios"
Is NOT supposed to be where it is at.
All the other entries are located like the Sony Vegas is.

Any idea's on what might have caused this to happen?
{
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/7NLyhJdgka6_LBW6GRBKCGXMTeg\"",
   "id": "PLoGpay6XnQnSlFWJtSLoJ_aMHvGgZ7PMH",
   "snippet": {
    "publishedAt": "2015-03-03T01:58:03.000Z",
    "channelId": "UC0crFgTrPx5t6YM2NumtFoA",
    "title": "Visual Studio",
    "description": "Creating interactive vb.net websites with Microsoft Visual Studio.",
    "channelTitle": "Dark Effects Studios"
   },
   "contentDetails": {
    "itemCount": 16
   }
  },
  {
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/RcMiXYTLjuAco7pekn8tuvzPRK4\"",
   "id": "PLoGpay6XnQnSWNTZhznLGDLB813NLsLjM",
   "snippet": {
    "publishedAt": "2015-02-22T03:45:49.000Z",
    "channelId": "UC0crFgTrPx5t6YM2NumtFoA",
    "title": "Sony Vegas 13",
    "description": "Sony Vegas 13.\nThis fully features version release, is sure to get you up and running quickly, so you can get your production to your client or audience.",
    "thumbnails": {
     "standard": {
      "url": "https://i.ytimg.com/vi/FbRH0wPZ32o/sddefault.jpg"
     }
    },
    "channelTitle": "Dark Effects Studios"
   },
   "contentDetails": {
    "itemCount": 37
   }
  },

Open in new window

Assuming that what you are showing me is from the youtube api, you would have to approach youtube to determine the reason for the apparent mixup.

As for the reason the null check produced fewer results.  This is what the null check is supposed to do, if you find that you have null values then unless your datafield in the database supports a null, you don't provide data; by the same rights, you don't try to read properties of a null property.

-saige-
Understand the NULL process.
Which is what showed me the issue with YouTube's JSON feed being incorrect in some of the values.

And the script here is what is stopping the values from being inserted into the database.
As there is NO thumbnail URL in the list.


            If [item].Snippet.Thumbnails IsNot Nothing Then
                If [item].Snippet.Thumbnails.Standard IsNot Nothing Then
                    If [item].Snippet.Thumbnails.Standard.Url IsNot Nothing Then

' Insert statement here

                    End If
                End If
            End If

Open in new window


Thanks -saige-
I am going to work on the other scripts now, using your concepts shown here.
And find a good forum to question about the misinformation on the YT JSON output.

Have a Rockin weekend.

Wayne
OK. Found out the issue.
I was using the [standard] for the image.
And it seems that it does not always show up.
I changed it to HQ [high] and it now works.
It even inserts the [Favorites] into the list as well, so it turns out that the Favorites has a thumbnail after all... Go figure.

I did this, and it keeps the [Favorites] out.

If Not item.Snippet.Title = "Favorites" Then
' Insert statement here
end if

Works like a charm now, with the [high] in-place now.

All is good.
This thread has now come to an end.
You Rock, -saige-.
Awsome, glad you got it sorted.

-saige-
-saige-
I did not want to bring another question in here.
But, I got stuck on the "tags []"
Could you please have a look here.

https://www.experts-exchange.com/questions/29016333/YouTube-API-get-the-Video-Tags-vb-net.html

Thanks.
Wayne