提问人:Luiz 提问时间:7/28/2023 最后编辑:dbcLuiz 更新时间:7/28/2023 访问量:152
在反序列化 JSON 缺少的属性时设置默认值
Set default value when deserializing JSON missing properties
问:
当我没有在JSON中列出属性时,我正在尝试为我的类分配默认值。
这是我用来反序列化 JSON 的类
Public Class cls_horarios
Public Class Expediente
Public Property expediente_opcao_domingo As ExpedienteOpcaoDomingo
Public Property expediente_opcao_segunda As ExpedienteOpcaoSegunda
Public Property expediente_opcao_terca As ExpedienteOpcaoTerca
Public Property expediente_opcao_quarta As ExpedienteOpcaoQuarta
Public Property expediente_opcao_quinta As ExpedienteOpcaoQuinta
Public Property expediente_opcao_sexta As ExpedienteOpcaoSexta
Public Property expediente_opcao_sabado As ExpedienteOpcaoSabado
Public Property expediente_feriados As String
Public Property expediente_bloqueio_pc As String
Public Property expediente_bloqueio_tolerancia As String
End Class
Public Class ExpedienteOpcaoDomingo
Public Property isDiaUtil As Integer
Public Property hora_inicial As String
Public Property hora_final As String
End Class
Public Class ExpedienteOpcaoQuarta
Public Property isDiaUtil As Integer
Public Property hora_inicial As String
Public Property hora_final As String
End Class
Public Class ExpedienteOpcaoQuinta
Public Property isDiaUtil As Integer
Public Property hora_inicial As String
Public Property hora_final As String
End Class
Public Class ExpedienteOpcaoSegunda
Public Property isDiaUtil As Integer
Public Property hora_inicial As String
Public Property hora_final As String
End Class
Public Class ExpedienteOpcaoSexta
Public Property isDiaUtil As Integer
Public Property hora_inicial As String
Public Property hora_final As String
End Class
Public Class ExpedienteOpcaoTerca
Public Property isDiaUtil As Integer
Public Property hora_inicial As String
Public Property hora_final As String
End Class
Public Class Result
Public Property expediente As List(Of Expediente)
End Class
Public Class Root
Public Property result As Result
End Class
这是我尝试反序列化的 JSON:
{
"result": {
"expediente": [{
"expediente_opcao_domingo": {
"isDiaUtil": 0,
"hora_inicial": null,
"hora_final": null
},
"expediente_opcao_segunda": {
"isDiaUtil": 1,
"hora_inicial": "09:00",
"hora_final": "18:48"
},
"expediente_opcao_terca": {
"isDiaUtil": 1,
"hora_inicial": "09:00",
"hora_final": "18:48"
},
"expediente_opcao_quarta":
{
"isDiaUtil": 1,
"hora_inicial": "09:00",
"hora_final": "18:48"
},
"expediente_opcao_sexta": {
"isDiaUtil": 1,
"hora_inicial": "09:00",
"hora_final": "18:48"
},
"expediente_opcao_sabado": {
"isDiaUtil": 0,
"hora_inicial": null,
"hora_final": null
},
"expediente_nome": "padr\u00e3o",
"expediente_feriados": "0",
"expediente_bloqueio_pc": 0,
"expediente_bloqueio_tolerancia": "0"
}],
}
}
在这种情况下,我尝试做的是分配一个默认值,使其在JSON中没有属性,设置默认值,以便可以对其进行测试,只需删除JSON中标识的行即可
这是我用来读取 JSON 的代码
Public Sub PreencheConfiguracoesColaborador(ByVal dados As String)
'//INICIO EXPEDIENTE DO COLABORADOR
Dim horarioColab As cls_horarios.Root = JsonConvert.DeserializeObject(Of cls_horarios.Root)(dados)
expediente_colab_quantidade = 0
Try
For Each item As Expediente In horarioColab.result.expediente
expediente_colab_feriado = item.expediente_feriados
expediente_colab_bloqueio_pc = item.expediente_bloqueio_pc
expediente_colab_bloqueio_tolerancia = item.expediente_bloqueio_tolerancia
expediente_colab_domingo = item.expediente_opcao_domingo.isDiaUtil
expediente_colab_domingo_hora_entrada = FormatDateTime(item.expediente_opcao_domingo.hora_inicial.ToString, DateFormat.LongTime)
expediente_colab_domingo_hora_saida = FormatDateTime(item.expediente_opcao_domingo.hora_final.ToString, DateFormat.LongTime)
expediente_colab_segunda = item.expediente_opcao_segunda.isDiaUtil
expediente_colab_segunda_hora_entrada = FormatDateTime(item.expediente_opcao_segunda.hora_inicial.ToString, DateFormat.LongTime)
expediente_colab_segunda_hora_saida = FormatDateTime(item.expediente_opcao_segunda.hora_final.ToString, DateFormat.LongTime)
expediente_colab_terca = item.expediente_opcao_terca.isDiaUtil
expediente_colab_terca_hora_entrada = FormatDateTime(item.expediente_opcao_terca.hora_inicial.ToString, DateFormat.LongTime)
expediente_colab_terca_hora_saida = FormatDateTime(item.expediente_opcao_terca.hora_final.ToString, DateFormat.LongTime)
expediente_colab_quarta = item.expediente_opcao_quarta.isDiaUtil
expediente_colab_quarta_hora_entrada = FormatDateTime(item.expediente_opcao_quarta.hora_inicial.ToString, DateFormat.LongTime)
expediente_colab_quarta_hora_saida = FormatDateTime(item.expediente_opcao_quarta.hora_final.ToString, DateFormat.LongTime)
expediente_colab_quinta = item.expediente_opcao_quinta.isDiaUtil
expediente_colab_quinta_hora_entrada = FormatDateTime(item.expediente_opcao_quinta.hora_inicial.ToString, DateFormat.LongTime)
expediente_colab_quinta_hora_saida = FormatDateTime(item.expediente_opcao_quinta.hora_final.ToString, DateFormat.LongTime)
expediente_colab_sexta = item.expediente_opcao_sexta.isDiaUtil
expediente_colab_sexta_hora_entrada = FormatDateTime(item.expediente_opcao_sexta.hora_inicial.ToString, DateFormat.LongTime)
expediente_colab_sexta_hora_saida = FormatDateTime(item.expediente_opcao_sexta.hora_final.ToString, DateFormat.LongTime)
expediente_colab_sabado = item.expediente_opcao_sabado.isDiaUtil
expediente_colab_sabado_hora_entrada = FormatDateTime(item.expediente_opcao_sabado.hora_inicial.ToString, DateFormat.LongTime)
expediente_colab_sabado_hora_saida = FormatDateTime(item.expediente_opcao_sabado.hora_final.ToString, DateFormat.LongTime)
'expediente_colab_expediente_nome = item.expediente_nome
expediente_colab_quantidade += 1
Console.WriteLine("Feriado: " & expediente_colab_feriado & " Bloqueio Pc: " & expediente_colab_bloqueio_pc & " Bloqueio Tolerancia: " & expediente_colab_bloqueio_tolerancia & " Expediente Nome: " & expediente_colab_expediente_nome)
Next
Catch ex As Exception
writeExeption(ex, False)
Console.WriteLine("Erro Expediente: " & ex.Message)
End Try
End Sub
我已经在 SO 上尝试了以下建议的解决方案:
为什么当我使用 JSON.NET 反序列化时会忽略我的默认值?
但都没有成功。
我需要的是当缺少JSON属性时设置默认值,因此我请求大家的帮助来解决此问题。
答:
您在这里遇到了一些问题:
JSON 中没有该属性的值,因此是 。
"expediente_opcao_quinta"
Expediente.expediente_opcao_quinta
null
有几个字符串在 JSON 中的值显式为 null,例如 .
"result[0].expediente.expediente_opcao_sabado"
此外,还缺少字符串值属性,其值默认为 。
null
解决这些问题的最简单方法是在构造时自动将属性初始化为非 null 值,如初始化自动实现的属性中所示,并将 <JsonProperty(NullValueHandling := NullValueHandling.Ignore)>
应用于不应为 null 的任何属性,以强制 Json.NET 在反序列化和序列化时忽略 null 值。
因此,您的数据模型应如下所示:
Public Class Expediente
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property expediente_opcao_domingo As ExpedienteOpcao = New ExpedienteOpcao()
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property expediente_opcao_segunda As ExpedienteOpcao = New ExpedienteOpcao()
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property expediente_opcao_terca As ExpedienteOpcao = New ExpedienteOpcao()
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property expediente_opcao_quarta As ExpedienteOpcao = New ExpedienteOpcao()
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property expediente_opcao_quinta As ExpedienteOpcao = New ExpedienteOpcao()
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property expediente_opcao_sexta As ExpedienteOpcao = New ExpedienteOpcao()
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property expediente_opcao_sabado As ExpedienteOpcao = New ExpedienteOpcao()
Public Property expediente_feriados As String
Public Property expediente_bloqueio_pc As String
Public Property expediente_bloqueio_tolerancia As String
End Class
Public Class ExpedienteOpcao
Public Property isDiaUtil As Integer
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property hora_inicial As String = ""
<JsonProperty(NullValueHandling := NullValueHandling.Ignore)> _
Public Property hora_final As String = ""
End Class
Public Class Result
Public Property expediente As List(Of Expediente)
End Class
Public Class Root
Public Property result As Result
End Class
笔记:
你有七个相同的类,名称像 和 似乎对应于一周中的几天。我猜你是用一些代码生成工具创建的这些类的。代码生成工具有时无法检测和组合相同的类型,但由于在这种情况下它们似乎应该是相同的,所以我在回答中将它们设置为相同。
ExpedienteOpcaoDomingo
ExpedienteOpcaoQuarta
在您的问题中,您可以捕获并忽略所有异常。这通常是一个坏主意,因为您丢失了有关问题原因的所有信息,并且您的代码可能会使用损坏的数据继续。例如,参见 捕获一般异常真的是一件坏事吗?
虽然可以使用“缺少属性的默认值”中的答案 JSON.net 用于为具有基元值的缺失属性提供默认值,但不能用于为复杂属性值提供默认值,例如,由于 CLR 中内置的特性参数类型的限制。
DefaultValueAttribute
DefaultValueAttribute
ExpedienteOpcao
在这里演示小提琴。
评论
<DefaultValue(1)> Public Property isDiaUtil As Integer
isDiaUtil
1