如何将null设置为json的特定属性?

时间:2016-01-04 12:20:11

标签: json vb.net

我创建了一个json,用于保存公司业务逻辑的设置。现在的问题是,如果一天不起作用,我应该在json这个结构中:

{"monday":{"start":"09:00","end":"19:00","breaks":[{"start":"10:30","end":"10:40"},{"start":"15:30","end":"16:40"}]},"tuesday":null,"...

如何看待monday有一个开始和结束工作时段,并且还有一个breaks表示非工作时间时段。无论如何,我从我的代码得到的结果是:

{"monday":{"start":"09:00","end":"19:00","breaks":[]},"tuesday":{"start":null,"end":null,"breaks":[]},

tuesday是一个没有工作的日子,所以我希望获得将json放在顶部,如我所示。这是我的代码:

Public Class WorkDay            'working day

    <JsonProperty("start")>
    Public Property starttime As String
    <JsonProperty("end")>
    Public Property endtime As String 
    Public Property breaks As New List(Of Break)

End Class

Public Class Break              'Breaks time slot

    <JsonProperty("start")>
    Public Property starttime As String
    <JsonProperty("end")>
    Public Property endtime As String

End Class

Public Class WorkWeek           'Class for working days

    Public Property monday As WorkDay
    Public Property tuesday As WorkDay
    Public Property wednesday As WorkDay
    Public Property thursday As WorkDay
    Public Property friday As WorkDay
    Public Property saturday As WorkDay
    Public Property sunday As WorkDay

    'Instance

    Public Sub New()
        monday = New WorkDay
        tuesday = New WorkDay
        wednesday = New WorkDay
        thursday = New WorkDay
        friday = New WorkDay
        saturday = New WorkDay
        sunday = New WorkDay
    End Sub

End Class

班级WorkDay每天都以monday, tuesday, wednesday etc...的形式出现。我还有休息时间段的break类。以及课程WorkWeek中的天数列表。现在我按照json这样的某一天定价:

WorkWeek.tuesday.starttime = tuesday_start.Text
WorkWeek.tuesday.endtime = tuesday_end.Text

每天都在select stament这样:

For Each c As CheckBox In GroupBox2.Controls.OfType(Of CheckBox)

        If c.Checked = True Then

            'Check working day

            Select Case c.Name

                Case "monday"

                    WorkWeek.monday.starttime = monday_start.Text
                    WorkWeek.monday.endtime =monday_end.Text

                Case "tuesday"

                    WorkWeek.tuesday.starttime = tuesday_start.Text
                    WorkWeek.tuesday.endtime = tuesday_end.Text

 'Generating..
Dim jstr = JsonConvert.SerializeObject(WorkWeek)

checked属性出现在工作日,事实上我的操作员可以取消选中非工作日。所以我的代码只对工作日进行了评估。我想知道如果星期二是非工作日,我可以设置"tuesday":null,"而不是"tuesday":{"start":null,"end":null,"breaks":[]}。想法?

3 个答案:

答案 0 :(得分:1)

罗兰是正确的。

或者您可以添加自己的自定义转换器:

Friend Class WorkWeekConverter
Inherits JsonConverter

Private ReadOnly _type as Type = GetType(WorkWeek)

Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
    Dim ww = DirectCast(value, WorkWeek)
    writer.WriteStartObject()
    WriteWorkDay(writer, ww, serializer, NameOf(WorkWeek.monday))
    WriteWorkDay(writer, ww, serializer, NameOf(WorkWeek.tuesday))
    WriteWorkDay(writer, ww, serializer, NameOf(WorkWeek.wednesday))
    WriteWorkDay(writer, ww, serializer, NameOf(WorkWeek.thursday))
    WriteWorkDay(writer, ww, serializer, NameOf(WorkWeek.friday))
    WriteWorkDay(writer, ww, serializer, NameOf(WorkWeek.saturday))
    WriteWorkDay(writer, ww, serializer, NameOf(WorkWeek.sunday))
    writer.WriteEndObject()
End Sub

Private Sub WriteWorkDay(writer As JsonWriter, ww As WorkWeek, serializer As JsonSerializer, dayOfWeek As String)
    Dim prop = _type.GetProperty(dayOfWeek)
    Dim value = DirectCast(prop.GetValue(ww), WorkDay)
    writer.WritePropertyName(dayOfWeek)
    If value?.IsSet Then
        serializer.Serialize(writer, value)
    Else
        serializer.Serialize(writer, Nothing)
    End If
End Sub

Public Overrides Function CanConvert(objectType As Type) As Boolean
    Return objectType = GetType(WorkWeek)
End Function

Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
    Throw New NotImplementedException()
End Function

End Class

为WorkDay添加一个便利属性,如下所示:

Public Class WorkDay            'working day

<JsonProperty("start")>
Public Property starttime As String
<JsonProperty("end")>
Public Property endtime As String
Public Property breaks As New List(Of Break)

Friend ReadOnly Property IsSet As Boolean
    Get
        Return Not (String.IsNullOrEmpty(starttime) AndAlso
                    String.IsNullOrEmpty(endtime))
    End Get
End property

End Class

您可以在序列化对象时指定转换器:

Dim s = JsonConvert.SerializeObject(x, new WorkWeekConverter())

这给了你:

{&#34;星期一&#34;:{&#34;开始&#34;:&#34;今天&#34;,&#34;结束&#34;:&#34;今天,晚上&#34 ;,&#34;场所&#34;:[]},&#34;星期二&#34;:空,&#34;星期三&#34;:空,&#34;周四&#34;:空,&# 34;周五&#34;:空,&#34;星期六&#34;:空,&#34;周日&#34;:空}

即如果x等于:

Dim x As New WorkWeek
x.monday.starttime = "today"
x.monday.endtime="today, evening"

答案 1 :(得分:1)

获得所需结果的一种方法是摆脱WorkWeek类并在其位置使用字典。在另一个问题中,您将数据反序列化为一个,无论如何都要将其用作集合。因此:

' or use a string array to enforce the name and casing
Public Enum WkDays
    sunday
    monday
    tuesday
    wednesday
    thursday
    friday
    saturday
End Enum

Dim wrkwk As New Dictionary(Of WkDays, WorkDay)    
For Each v As WkDays In [Enum].GetValues(GetType(WkDays))
    wrkwk.Add(v, New WorkDay)
Next

使用新的空WorkDay对象初始化集合非常重要,这样您就不必在任何地方检查Nothing。为此,您可以使用一个函数来确保它始终发生。此版本使用字符串数组作为键:

Private Function GetNewWorkWeek() As Dictionary(Of String, WorkDay)
    Dim days = {"sunday", "monday", "tuesday", "wednesday",
                "thursday", "friday", "saturday"}

    Dim wrkwk As New Dictionary(Of String, WorkDay)
    ' add new, empty WorkDay objects
    For Each d As String In days
        wrkwk.Add(d, New WorkDay)
    Next
    Return wrkwk
End Function

' usage:
Dim wrkwk = GetNewWorkWeek()

由于存在/指定5或7天可能是最正常的,通过使用空WorkDay个对象初始化它,您不必在代码中散布If x IsNot Nothing。而不是必须检查和创建工作日,从词典中获取一个工作日:

' get a workday to work with
Dim wd As WorkDay = wrkwk(WkDays.sunday)
wd.starttime = "08:00"
wd.endtime = "17:30"
Dim b As New Break
b.starttime = "10:05"
b.endtime = "10:20"
wd.breaks.Add(b)
' etc

对于假期,您可以删除该工作日,但它只是不在列表中,使其显示为“null”使其成为Nothing

wrkwk(WkDays.tuesday) = Nothing

Dim jstr = JsonConvert.SerializeObject(wrkwk)

结果:

{
"sunday": {
    "start": "08:00",
    "end": "17:30",
    "breaks": [{
        "start": "10:05",
        "end": "10:20"
    }, {
        "start": "14:05",
        "end": "14:20"
    }]
},
"monday": {
   ...
},
"tuesday": null,
"wednesday": {

当然,它会反序列化回字典就好了。有几种方法可以解决它并使用它。客户转换器也是一个好主意。

在这种情况下,您至少应该考虑删除tuesday对象。测试这个更容易:

If myWorkWeek.ContainsKey(WkDays.tusday) Then...

而不是在任何地方(即使你每年有364天的数据,因为ONE可能为null,所有代码都必须考虑到这一点!):

If myWorkWeek(n) IsNot Nothing Then...

答案 2 :(得分:0)

要为生成的JSON设置null tuesday,您需要WorkWeek上的相应对象为Nothing - 但是在您的构造函数中,你明确地创建它。您希望按需创建,或在适当时清除它。