4

I am currently writing an API which is taking objects from a web service handling it in VB.net using the Newsoft JSON .NET library.

I'm deserializing a JSON array called Vehicles into a list of vehicles.

Here is the important code snippets:

Public Class VehicleList
    Public Vehicles() As Vehicle
End Class

Public Class Vehicle
    Public Property licence_plate_number As String
End Class

Here we have a web client that grabs the json and put it into the objects.

Public Class dcVehicles

    Private Property _Vehicles As VehicleList

    Public ReadOnly Property Vehicle As Vehicle()
        Get
            Return _Vehicles.Vehicles
        End Get
    End Property

    Public Sub Refresh()
        _Vehicles = JsonConvert.DeserializeObject(Of VehicleList)(wcReply, jsSettings)
    End Sub
End Class

There's slightly more to it (cut it down). So everything is working as intended, json net is creating an array of vehicles.

I'm trying to achieve this with the properties in the vehicle class as private and read only, the applications using the api should not be able to set these.

The problem is I've tried changing the public property in the vehicle class to keep the property private and allow readonly as below:

Public Class Vehicle
    Friend Property licence_plate_number As String

    Public ReadOnly Property RegistrationNumber As String
        Get
            Return licence_plate_number
        End Get
    End Property
End Class

The problem I then get is that JSON.net is unable to populate the vehicles. All 3 classes are in the same namespace. So I tried licence_plate_number with the Friend/private access level modifier but still Json net is unable to populate the object.

The only way is keeping it as Public.

Does anyone have an idea for a work-around? Or is am I missing something simple?

Thanks

Pure
  • 158
  • 9
  • Can you provide a sample of the json? – djv Oct 20 '16 at 15:08
  • 2
    Anyway, you can't directly serialize private members. There are solutions however, see (C#) http://stackoverflow.com/questions/10189471/json-net-serialize-private-members-and-not-readonly-properties, http://stackoverflow.com/questions/32008869/json-net-serialize-specific-private-field – djv Oct 20 '16 at 15:13
  • What do you want to see in the JSON for `Vehicle`? `RegistrationNumber` or `licence_plate_number`? – dbc Oct 20 '16 at 17:26
  • Thanks for the help, I can add an example of the json. The json has licence_plate_number but I want to store it in the readonly property RegistrationNumber. – Pure Oct 20 '16 at 19:38

1 Answers1

1

If you just want to serialize a Private or Friend property with Json.NET, mark it with <JsonProperty> and mark the public readonly property you don't want to serialize with <JsonIgnore>:

Public Class Vehicle
    <JsonProperty> _
    Friend Property licence_plate_number As String

    <JsonIgnore> _
    Public ReadOnly Property RegistrationNumber As String
        Get
            Return licence_plate_number
        End Get
    End Property
End Class

Demo fiddle.

But if you really want read-only value semantics for the licence_plate_number property so that it cannot be set after construction, you can do this by replacing the default constructor with a single parameterized constructor and matching the constructor argument names to the JSON property names, like so:

Public Class Vehicle
    Private Readonly licence_plate_number As String

    Public Sub New(ByVal licence_plate_number as String)
        Me.licence_plate_number = licence_plate_number
    End Sub

    <JsonProperty("licence_plate_number")> _
    Public ReadOnly Property RegistrationNumber As String
        Get
            Return licence_plate_number
        End Get
    End Property
End Class

When there is a single public constructor that is parameterized, Json.NET will call it, matching the constructor arguments to the JSON properties by name using reflection and using default values for missing properties. Matching by name is case-insensitive, unless there are multiple matches that differ only in case, in which case the match becomes case sensitive.

Demo fiddle.

If your class has multiple public constructors, mark the one to use with <JsonConstructor>.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • 1
    Great, this looks like this jsonproperty specifier is exactly what I'm after. I'm going to try it tomorrow to see is Json.net then populates the vehicles class, when using the Friend modifier. As for populating the property on new(), I cannot use this method as another class may need to change a value later. It's handy to know the second method too and I'm sure It'll come to good use, I'm always working with json net now and enjoying it. – Pure Oct 21 '16 at 02:06
  • Great this is working. The API (dcVehicles) is populating the Friend properties of Vehicle, and the application can use the Public ReadOnly property to do exactly what it needs. To conclude, to populate Friend or Private properties with the Json net library json net needs to be marked with an extra attribute . Whereas it appears that if the property or variable is Public this is not necessary. Thanks. – Pure Oct 21 '16 at 11:16
  • So if you want readonly or private properties to be deserialized you will need a special constructor for json – user4951 Nov 16 '22 at 13:04