英文:
Set default value when deserializing JSON missing properties
问题
我正在尝试为我的类分配一个默认值,当JSON中没有列出属性时。
这是我用于反序列化JSON的类:
Public Class cls_horarios
' ... 你的类定义
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ão",
"expediente_feriados": "0",
"expediente_bloqueio_pc": 0,
"expediente_bloqueio_tolerancia": "0"
}]
}
}
在这种情况下,我正在尝试分配一个默认值,以便在JSON中没有这些属性时设置默认值,只需删除JSON中标识的行。
这是我用于读取JSON的代码:
Public Sub PreencheConfiguracoesColaborador(ByVal dados As String)
' ... 你的代码
End Sub
我已经尝试了在SO上提出的一些解决方案,但都没有成功。我需要在JSON属性缺失时设置默认值,所以我请求大家的帮助来解决这个问题。
英文:
I'm trying to assign a Default value to my class, when I don't have the property listed in the JSON.
This is the class I'm using to deserialize 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
This is the JSON I am trying to deserialize:
{
"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"
}],
}
}
In this scenario, what I'm trying to do is assign a default value so that it doesn't have the properties in the JSON, the default value is set, so that it can be tested, just remove the line that is identified in the JSON
and this is the code I'm using to read the 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
I have already tried the following proposed solutions right here on SO:
https://stackoverflow.com/questions/29611445/default-value-for-missing-properties-with-json-net
But all without success.
What I need is to set the default value when the JSON properties are missing, so I ask for everyone's help to resolve this issue.
答案1
得分: 0
以下是翻译好的部分:
-
在JSON中没有为属性
"expediente_opcao_quinta"
提供值,因此Expediente.expediente_opcao_quinta
为null
。 -
有几个字符串在JSON中的值明确为null,例如
"result[0].expediente.expediente_opcao_sabado"
。 -
也有缺少字符串值属性,其值默认为
null
。
解决这些问题的最简单方法是在构造时自动将属性初始化为非null值,如Initializing an Auto-Implemented Property中所示,并对任何永远不应为null的属性应用<JsonProperty(NullValueHandling := NullValueHandling.Ignore)>
以强制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
,看起来对应于一周中的每一天。我猜您使用了某种代码生成工具创建了这些类。代码生成工具有时会无法检测并合并相同的类型,但在这种情况下,它们似乎应该是相同的,因此在我的答案中我将它们设为相同。 -
在您的问题中,您捕获并忽略所有异常。这通常是一个不好的做法,因为您会丢失有关问题原因的所有信息,而且您的代码可能会继续使用损坏的数据前进。有关更多讨论,请参阅Is catching general exceptions really a bad thing?。
-
尽管您可以使用来自https://stackoverflow.com/q/29611445/3744182的答案来使用
DefaultValueAttribute
为具有原始值的缺少属性提供默认值,但由于CLR内置了对属性参数类型的限制,因此无法使用DefaultValueAttribute
为ExpedienteOpcao
等复杂属性值提供默认值。
演示示例位于此处。
英文:
You have a few problems here:
-
There is no value for the property
"expediente_opcao_quinta"
in the JSON, thusExpediente.expediente_opcao_quinta
isnull
. -
There are several string whose values in the JSON is explicitly null, e.g.
"result[0].expediente.expediente_opcao_sabado"
. -
There are also missing string-valued properties whose values default to
null
.
The easiest way to resolve these problems is to automatically initialize your properties to non-null values when constructed as shown in Initializing an Auto-Implemented Property, and apply <JsonProperty(NullValueHandling := NullValueHandling.Ignore)>
to any property that should never be null to force Json.NET to ignore null values when deserializing and serializing.
Thus your data model should look like:
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
Notes:
-
You have a seven of identical classes with names like
ExpedienteOpcaoDomingo
andExpedienteOpcaoQuarta
that seem to correspond to days of the week. I am guessing you created these classes with some code generation tool. Code generation tools will sometimes fail to detect and combine identical types, but since in this case it seems they should be identical, I made them such in my answer. -
In your question you catch and ignore all exceptions. This is generally a bad idea as you lose all information about the cause of the problem, and your code may proceed forward using corrupt data. See e.g. Is catching general exceptions really a bad thing? for some additional discussion.
-
While you could use the answers from https://stackoverflow.com/q/29611445/3744182 to use
DefaultValueAttribute
to provide default values for missing properties with primitive values, you cannot useDefaultValueAttribute
to provide a default value for a complex property value such asExpedienteOpcao
due to limitations on attribute parameter types built into the CLR.
Demo fiddle here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论