0

I currently am trying to deserialize a JSON-object to a VB.NET-object. But I am not able to do that properly - but I guess I know the reason for it. Here is an example of my JSON-object:

{
  "USERNAME1": [
    {
      "workingTimes": [
        {
          "endDateAndTime": "20250524T105500Z",
          "beginDateAndTime": "20250524T102600Z",
          "workingTimeType": {
            "type": "wTime",
            "name": "wTime"
          },
          "name": "wTime",
          "type": "wTime",
          "id": "1"
        }
      ],
      "beginDate": "2025-01-01",
      "targetWorkingTimeMinutes": 0,
      "breakDurationMinutes": 0,
      "workingTimeMinutes": 20,
      "endDate": "2025-01-01"
    }
  ]
}

And my classes currently are:

Public Class COLLECTION
    Public Property USERS As New List(Of WORKDAY)
End Class

Public Class WORKDAY
    Public workingTimes As New List(Of WORKTIME)
    Public beginDate As String
    Public targetWorkingTimeMinutes As String
    Public breakDurationMinutes As String
    Public workingTimeMinutes As String
    Public endDate As String
End Class

Public Class WORKTIME
    Public endDateAndTime As String
    Public beginDateAndTime As String
    Public workingTimeType As WORKTIMETYPE
    Public name As String
    Public type As String
    Public id As String
End Class

Public Class WORKTIMETYPE
    Public type As String
    Public name As String
End Class

When I try to deserialize the JSON to my classes I just get errors. But I am sure that is caused because of the USERNAME1 that is a variable name and not a specified object (and yes, there can be multiple entries)!

If I change "Public Property USERS As New List(Of WORKDAY)" to "Public Property USERSNAME1 As New List(Of WORKDAY)" all seems to work fine!

I am a pretty newbie in JSON but I also tried to create a JSON using my classes and the result looks exactly like my example. So USERNAME1 must be the reason for my problems.

4
  • The following may be of interest: JSONUtils. Commented May 25 at 16:11
  • 1
    @Itallmakescents - jsonutils.com generates Public Property USERNAME1 As USERNAME1() but the querent needs to handle variable names. The already tried Public Property USERSNAME1 As New List(Of WORKDAY) and know it works, but that doesn't meet their needs. Commented May 25 at 16:15
  • @dbc: It seems that the JSON the OP provided is incomplete. USERNAME1 in the JSON seems to indicate that entry is for a single user. Whereas, the usage of USERS in the VB.NET code, seems to indicate that the JSON may contain more than one user which means that the OP needs to include a better JSON example (ie: more data). Commented May 25 at 16:25
  • @Itallmakescents - in general you are right that JSON samples should not be excessively simplified, but in this case their written text states USERNAME1 ... is a variable name and not a specified object (and yes, there can be multiple entries) so it's sufficiently clear that the root object has one or more variable properties, each having some user's name. Commented May 25 at 16:29

1 Answer 1

1

A few points:

  1. When you have a JSON object with arbitrary property names that are known only at runtime but that have some fixed schema for their value, use a Dictionary(Of String, Of TValue). In this case the schema for the value corresponds to a list of WorkDay objects, so use Dictionary(Of String, List(Of WorkDay)) for your root object type and eliminate the COLLECTION type entirely.

    You don't say what JSON serializer you are using, but dictionaries will work with both System.Text.Json and Newtonsoft.Json:

    Imports System.Text.Json
    
    JsonSerializer.Deserialize(Of Dictionary(Of String, List(Of WorkDay)))(json)
    

    or

    Imports Newtonsoft.Json
    
    Dim dict = JsonConvert.DeserializeObject(Of Dictionary(Of String, List(Of WorkDay)))(json)
    

    If using DataContractJsonSerializer you must first set DataContractJsonSerializerSettings.UseSimpleDictionaryFormat = true.

  2. I recommend using properties instead of fields for all of your public class members, as System.Text.Json only serializes properties by default.

  3. Several of your Minutes properties are numeric rather than textual:

      "targetWorkingTimeMinutes": 0,
      "breakDurationMinutes": 0,
      "workingTimeMinutes": 20,
    

    With some serializers (e.g. System.Text.Json) by default you need to use a numeric type such as Decimal or Integer to bind to numeric values, e.g.:

    Public Property targetWorkingTimeMinutes As Decimal
    Public Property breakDurationMinutes As Decimal
    Public Property workingTimeMinutes As Decimal
    
  4. I recommend using the naming conventions from MSFT's Visual Basic Naming Conventions for your type names. Thus I changed WORKDAY to WorkDay.

  5. Tools for generating .NET types from JSON generally will not automatically recognize when to use a Dictionary(Of String, of TValue) for a JSON object -- probably because there is no way to communicate to them that an object has variable names. (In fact many will generate duplicated types, one duplicate for each value.) Of the online tools mentioned in How to auto-generate a C# class file from a JSON string, only one, https://app.quicktype.io/#l=cs, will sometimes recognize dictionaries -- and when I tested it with your JSON with four root properties, it did not do so.

Putting it all together, your types should look like:

Public Class WorkDay
    Public Property workingTimes As New List(Of WorkTime)
    Public Property beginDate As String
    Public Property targetWorkingTimeMinutes As Decimal
    Public Property breakDurationMinutes As Decimal
    Public Property workingTimeMinutes As Decimal
    Public Property endDate As String
End Class

Public Class WorkTime
    Public Property endDateAndTime As String
    Public Property beginDateAndTime As String
    Public Property workingTimeType As WorkTimeType
    Public Property name As String
    Public Property type As String
    Public Property id As String
End Class

Public Class WorkTimeType
    Public Property type As String
    Public Property name As String
End Class

And sample code that deserializes your JSON could look like:

Dim dict = JsonSerializer.Deserialize(Of Dictionary(Of String, List(Of WorkDay)))(json)
    
For Each pair In dict
    Dim name = pair.Key
    Dim workDays = pair.Value
    
    Console.WriteLine($"Worker name {name}:")
    For Each workTime in workDays
        Console.WriteLine($"   Begin date: {workTime.beginDate}, Working Time Minutes: {workTime.workingTimeMinutes}, End Date: {workTime.endDate}")
    Next
Next

Sample System.Text.Json fiddle here and Json.NET fiddle here.

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

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.