Note: This question has a follow-up here:
Copy selected checkbox rows from DGV to DGV2 including image column
You need to download the images after the JSON
has been deserialized into your class object. You can and add a new public property of Type Bitmap to the internal Result
class, which will be used to present the Image referenced by the URI found in the JSON.
To aquire the Images, you need a method that takes the resource URI and downloads it from the remote machine. I added a public method to the Products
class, which references all the objects that contain a URI reference:
after the JSON
has been parsed successfully, the Results
property will reference all the Result
classes. Each Result
class will reference the Bitmap URI in the ProductImage
Property.
Using a WebClient
class, we can use these references to download the Images and add them to a Property of Type Bitmap.
We also need to instruct the JSON
parser to ignore this Property, since it's not part of the JSON
object.
This can be done adding a <JsonIgnore>
attribute to the property.
Rename the RootObject
(named JSON
in your class definition) to Root
:
Also, all the classes you're showing here are added to a Parent class
named ProductsQuery
, used as a container for all the class objects.
Public Class Root
Public Property uk As Uk
End Class
Deserialize the JSON with JsonConvert.DeserializeObject
:
Dim JSONObject As String = File.ReadAllText("[Source Txt]")
Dim JsonPost As ProductsQuery.Root = JsonConvert.DeserializeObject(Of ProductsQuery.Root)(JSONObject)
Use the newly added public method to download the images:
JsonPost.uk.ghs.Products.LoadImages()
Prepare the DataGridViewImageColumn that will show the Images:
Edit: also insert a DataGridViewCheckBoxColumn
.
Dim DGVCheckBoxCol As DataGridViewCheckBoxColumn = New DataGridViewCheckBoxColumn(False) With {
.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader,
.DisplayIndex = 0,
.HeaderText = "",
.Name = "Select"
}
Dim DGVImageCol As DataGridViewImageColumn = New DataGridViewImageColumn(False) With {
.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader,
.DataPropertyName = "Image",
.DisplayIndex = 1,
.FillWeight = 1,
.HeaderText = "Image",
.ImageLayout = DataGridViewImageCellLayout.Normal,
.Name = "Image",
.ValuesAreIcons = False
}
Then, set the DataGridView DataSource
and hide the Column that contains the Image URI, which is not really useful here. Also, call the AutoResizeRows method to set the size of the rows to better present the Image:
DataGridView1.DataSource = Nothing
DataGridView1.Columns.Clear()
DataGridView1.Columns.Insert(0, DGVCheckBoxCol)
DataGridView1.Columns.Insert(1, DGVImageCol)
DataGridView1.DataSource = JsonPost.uk.ghs.Products.Results
DataGridView1.Columns(2).Visible = False
DataGridView1.AutoResizeRows()
Result:

The modified classes:
Note:
The description
property is an array of strings, which the DGV refuses to show as it is. I've called it RawDescription
and I added a new property (Description
) of type String - with an <JsonIgnore>
attribute - in the Result
class, that will contain the flattened string.
Imports System.IO
Imports System.Net
Imports Newtonsoft.Json
Public Class ProductsQuery
Public Class Root
Public Property uk As Uk
End Class
Public Class Uk
Public Property ghs As Ghs
End Class
Public Class Ghs
Public Property products As Products
End Class
Public Class Products
Public Property input_query As String
Public Property output_query As String
Public Property filters As Filters
Public Property queryPhase As String
Public Property totals As Totals
Public Property config As String
<JsonProperty("results")>
Public Property Results As Result()
Public Property suggestions As Object()
Public Sub LoadImages()
Using client As WebClient = New WebClient()
For Each result As Result In Results
Dim bitmapBytes = client.DownloadData(result.ProductImage)
Using ms As MemoryStream = New MemoryStream(bitmapBytes)
ms.Position = 0
result.Image = CType(Image.FromStream(ms).Clone(), Bitmap)
End Using
result.ProductDescription = result.RawDescription(0)
Next
End Using
End Sub
End Class
Public Class Filters
End Class
Public Class Totals
Public Property all As Integer
<JsonProperty("new")>
Public Property NewProducts As Integer
Public Property offer As Integer
End Class
Public Class Result
<JsonIgnore>
Public Property Image As Bitmap
<JsonProperty("image")>
Public Property ProductImage As String
<JsonProperty("superDepartment")>
Public Property SuperDepartment As String
Public Property tpnb As Integer
Public Property ContentsMeasureType As String
<JsonProperty("name")>
Public Property Name As String
Public Property UnitOfSale As Integer
<JsonIgnore>
Public Property Description As String
<JsonProperty("description")>
Public Property RawDescription As String()
Public Property AverageSellingUnitWeight As Double
Public Property UnitQuantity As String
Public Property id As Integer
Public Property ContentsQuantity As Double
<JsonProperty("department")>
Public Property Department As String
<JsonProperty("price")>
Public Property Price As Double
<JsonProperty("unitprice")>
Public Property Unitprice As Double
End Class
End Class