Results 1 to 10 of 10

Thread: Json Deserialize to List of Class

  1. #1

    Thread Starter
    New Member
    Join Date
    Mar 2017
    Posts
    5

    Json Deserialize to List of Class

    Afternoon Everyone,

    I have not been coding for a very long time and a little rusty and been asked to knock up a little export utility that gets data from an API applies some various filters then exports to excel. I can grab the data from the API and I can export to excel easily but what I need to be able to do is deserialize from JSON into a list (of CustomClass) which is where I am drawing a blank. I have tried to research online and I am either not finding what I need or I am to dumb to understand (latter very probable).

    The difficulty is that there is a collection of items within the collection in the json.

    Here is my class for holding the data:

    Code:
    Public Class Ticket
        Public dt As DateTime
        Public summary As String
        Public issuetype As String
        Public team As String
        Public priority As Integer
        Public path As String
        Public caller As String
        Public CIPFA_priority As String
        Public person As String
        Public details As String
        Public messages As New List(Of message)
    End Class
    
    Public Class message
        Public from As String
        Public recip As String
        Public body As String
        Public DT As DateTime
        Public id As String
    End Class
    Here is a sample of the JSON that I get:

    Code:
    {
    	"records": {
    		"record": [{
    			"date": "Mon Jun 04 2018 16:31:18 GMT+0100 (BST)",
    			"summary": "Passenger lift",
    			"issuetype": "contractor",
    			"team": "unassigned",
    			"priority": "3",
    			"path": "Ground Floor: Ext. Lift",
    			"caller": "Staff Name Removed",
    			"CIPFA_priority": "",
    			"person": "Staff Name Removed",
    			"details": "Please carry out investigate of Lift not working.",
    			"allmessages": {
    				"messages": {
    					"message": {
    						"msgSubject": "New Helpdesk issue (contractor) (H-ID:000000-C00000-T000000): Ground Floor: Ext. Lift: 'lift '",
    						"msgTo": "Staff Name Removed",
    						"msgFrom": "Staff Name Removed",
    						"msgBody": "You have a new Helpdesk issue (contractor): Ground Floor: Lift: 'lift '\n\nHelpdesk issue (contractor) details:\nPlease carry out investigate of Lift not working.\n\nNOTE: either sender and recipient were the same or an attempt to also send this message by email and/or SMS on (Mon Jun 04 2018 16:31:30 GMT+0100 (BST)) was NOT successful. Please check relevant email/phone number details!",
    						"msgDate": "Mon Jun 04 2018 16:31:20 GMT+0100 (BST)"
    					}
    				}
    			},
    			"id": "00000",
    			"status": "in progress"
    		} ]
    	}
    }
    Any help is much appreciated!

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    35,619

    Re: Json Deserialize to List of Class

    Which version of VS are you using and what are you targeting (Framework, Core, etc)? The reason I ask is because JSON is a particularly moving target, of late, so the best approach is going to depend on your situation.
    My usual boring signature: Nothing

  3. #3
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    33,139

    Re: Json Deserialize to List of Class

    your Ticket class needs a property "allmessages" of type "messages"
    then you need a type "messages" that is a List (Of message).

    Wait... check that...
    Code:
    			"allmessages": {
    				"messages": {
    					"message": {
    						"msgSubject": "New Helpdesk issue (contractor) (H-ID:000000-C00000-T000000): Ground Floor: Ext. Lift: 'lift '",
    						"msgTo": "Staff Name Removed",
    						"msgFrom": "Staff Name Removed",
    						"msgBody": "You have a new Helpdesk issue (contractor): Ground Floor: Lift: 'lift '\n\nHelpdesk issue (contractor) details:\nPlease carry out investigate of Lift not working.\n\nNOTE: either sender and recipient were the same or an attempt to also send this message by email and/or SMS on (Mon Jun 04 2018 16:31:30 GMT+0100 (BST)) was NOT successful. Please check relevant email/phone number details!",
    						"msgDate": "Mon Jun 04 2018 16:31:20 GMT+0100 (BST)"
    					}
    				}
    			},
    There is nothing there that says messages or even allmessages is a collection... they are each a single object. And not even a collection of a singe object, but very straight up, an object, not a collection.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  4. #4

    Thread Starter
    New Member
    Join Date
    Mar 2017
    Posts
    5

    Re: Json Deserialize to List of Class

    Quote Originally Posted by Shaggy Hiker View Post
    Which version of VS are you using and what are you targeting (Framework, Core, etc)? The reason I ask is because JSON is a particularly moving target, of late, so the best approach is going to depend on your situation.
    2019 targeting .net Framework.

  5. #5

    Thread Starter
    New Member
    Join Date
    Mar 2017
    Posts
    5

    Re: Json Deserialize to List of Class

    Quote Originally Posted by techgnome View Post
    your Ticket class needs a property "allmessages" of type "messages"
    then you need a type "messages" that is a List (Of message).

    Wait... check that...
    Code:
    			"allmessages": {
    				"messages": {
    					"message": {
    						"msgSubject": "New Helpdesk issue (contractor) (H-ID:000000-C00000-T000000): Ground Floor: Ext. Lift: 'lift '",
    						"msgTo": "Staff Name Removed",
    						"msgFrom": "Staff Name Removed",
    						"msgBody": "You have a new Helpdesk issue (contractor): Ground Floor: Lift: 'lift '\n\nHelpdesk issue (contractor) details:\nPlease carry out investigate of Lift not working.\n\nNOTE: either sender and recipient were the same or an attempt to also send this message by email and/or SMS on (Mon Jun 04 2018 16:31:30 GMT+0100 (BST)) was NOT successful. Please check relevant email/phone number details!",
    						"msgDate": "Mon Jun 04 2018 16:31:20 GMT+0100 (BST)"
    					}
    				}
    			},
    There is nothing there that says messages or even allmessages is a collection... they are each a single object. And not even a collection of a singe object, but very straight up, an object, not a collection.

    -tg
    It is a collection just that example only has one message but it can have multiple. I don't have an example on me right now but will dig one out with multiple messages.

  6. #6
    Addicted Member
    Join Date
    Jun 2019
    Posts
    195

    Re: Json Deserialize to List of Class

    Get better example with more data, copy to clipboard, in Visual Studio use Edit|Paste Special|Paste JSON As Classes and see the generated classes. They may need some fixes to get it working. You will see how much different are the generated ones from what you defined as Ticket and Message classes.

  7. #7
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    33,139

    Re: Json Deserialize to List of Class

    Quote Originally Posted by MCRO View Post
    It is a collection just that example only has one message but it can have multiple. I don't have an example on me right now but will dig one out with multiple messages.
    Do, becaue the current example doesn't indicate that it can be a collection... Even if there's only one, if it's intended to be part of a list/collection, it should be surrounded by square brackets.


    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  8. #8
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    9,892

    Re: Json Deserialize to List of Class

    Quote Originally Posted by peterst View Post
    Get better example with more data, copy to clipboard, in Visual Studio use Edit|Paste Special|Paste JSON As Classes and see the generated classes. They may need some fixes to get it working. You will see how much different are the generated ones from what you defined as Ticket and Message classes.
    I was not aware of this, I've been defining my classes by hand.

  9. #9
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,552

    Re: Json Deserialize to List of Class

    Try the following

    Code:
    Imports System.IO
    '
    ' NuGet package below
    '
    Imports System.Text.Json
    
    Public Class Form1
        Private Sub DeserializeButton_Click(sender As Object, e As EventArgs) Handles DeserializeButton.Click
            Dim fileName = "json.json"
            Dim json = File.ReadAllText(fileName)
            Dim results As RecordRoot = JsonSerializer.Deserialize(Of RecordRoot)(json)
        End Sub
    End Class
    '
    ' Classes below to be in their own class files.
    '
    Public Class RecordRoot
        Public Property records As Records
    End Class
    
    Public Class Records
        Public Property record() As Record()
    End Class
    
    Public Class Record
        Public Property _date As String
        Public Property summary As String
        Public Property issuetype As String
        Public Property team As String
        Public Property priority As String
        Public Property path As String
        Public Property caller As String
        Public Property CIPFA_priority As String
        Public Property person As String
        Public Property details As String
        Public Property allmessages As Allmessages
        Public Property id As String
        Public Property status As String
    End Class
    
    Public Class Allmessages
        Public Property messages As Messages
    End Class
    
    Public Class Messages
        Public Property message As Message
    End Class
    
    Public Class Message
        Public Property msgSubject As String
        Public Property msgTo As String
        Public Property msgFrom As String
        Public Property msgBody As String
        Public Property msgDate As String
    End Class

    Attachment 179314

  10. #10

    Thread Starter
    New Member
    Join Date
    Mar 2017
    Posts
    5

    Re: Json Deserialize to List of Class

    Thank you for the great advice has taught me a couple of things which is really helpful such as pasting as class! Never knew that.

    I am having a little bit of an issue though. So I took my entire JSON output (over 18,000 lines) and pasted as class. I then took the the deserializer line of code which is where it errors:

    Code:
    Dim results As Rootobject = JsonSerializer.Deserialize(Of Rootobject)(json)
    The error is:

    System.Text.Json.JsonException: 'The JSON value could not be converted to Flow_360_API.Record. Path: $.record | LineNumber: 1 | BytePositionInLine: 12.'

    This exception was originally thrown at this call stack:
    [External Code]
    Flow_360_API.Flow360API.ActiveIssuesSummary(String) in Flow360API.vb
    Flow360_Exporter.Form1.Button1_Click(Object, System.EventArgs) in Form1.vb
    [External Code]

    The code is as follows:

    Code:
        Public Function ActiveIssuesSummary(Optional Team As String = Nothing) As Rootobject
    
            Dim json As String = webClient.DownloadString("https://url.here/request/?info1=info")
    
            json = json.Substring(11, json.Length - (12))
           
            Dim results As Rootobject = JsonSerializer.Deserialize(Of Rootobject)(json)
    
            Return results
    
        End Function
    The reason for the substring is the json that gets returned fails json validator online as it has some extran bumf at the start and end so I cam just removing that but passes as valid json post cleanup.

    Here are the classes generated:

    Code:
    Public Class Rootobject
        Public Property record() As Record
    End Class
    
    Public Class Record
        Public Property _date As String
        Public Property summary As String
        Public Property issuetype As String
        Public Property team As String
        Public Property priority As String
        Public Property path As String
        Public Property caller As String
        Public Property CIPFA_priority As String
        Public Property person As String
        Public Property details As String
        Public Property allmessages As Allmessages
        Public Property id As String
        Public Property status As String
    End Class
    
    Public Class Allmessages
        Public Property messages As Messages
    End Class
    
    Public Class Messages
        Public Property message As Object
    End Class
    and finally here is a subset of the information in the json request and it fails if I manually pass just this subset through with the same error:

    Code:
    {
    	"record": [{
    		"date": "Fri Nov 27 2020 12:40:00 GMT-0000 (GMT)",
    		"summary": "IT: Monday period 3 and 4",
    		"issuetype": "ICT Service",
    		"team": "IT Support",
    		"priority": "",
    		"path": "123",
    		"caller": "123",
    		"CIPFA_priority": "",
    		"person": "unassigned",
    		"details": "123",
    		"allmessages": {
    			"messages": {
    				"message": {
    					"msgSubject": "123",
    					"msgTo": "123",
    					"msgFrom": "123",
    					"msgBody": "123",
    					"msgDate": "Fri Nov 27 2020 12:40:00 GMT-0000 (GMT)"
    				}
    			}
    		},
    		"id": "123",
    		"status": "open"
    	}, {
    		"date": "Fri Nov 27 2020 14:18:56 GMT-0000 (GMT)",
    		"summary": "Projector for installation film",
    		"issuetype": "ICT service",
    		"team": "IT Support",
    		"priority": "",
    		"path": "123",
    		"caller": "123",
    		"CIPFA_priority": "",
    		"person": "unassigned",
    		"details": "123",
    		"allmessages": {
    			"messages": {
    				"message": [{
    					"msgSubject": "123",
    					"msgTo": "123",
    					"msgFrom": "123",
    					"msgBody": "123",
    					"msgDate": "Fri Nov 27 2020 14:18:58 GMT-0000 (GMT)"
    				}, {
    					"msgSubject": "123",
    					"msgTo": "123",
    					"msgFrom": "123",
    					"msgBody": "123",
    					"msgDate": "Fri Nov 27 2020 14:18:58 GMT-0000 (GMT)"
    				}]
    			}
    		},
    		"id": "1372376",
    		"status": "open"
    	}]
    }

    123 values have been replaced due to confidential informaiton
    Last edited by MCRO; Nov 30th, 2020 at 08:33 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width