【发布时间】:2021-10-14 14:08:01
【问题描述】:
情况
我在实现 .NET Core 的 System.Text.Json.JsonSerializer 时遇到了问题。 我的应用程序用于获取数据的 API 返回以下格式的 JSON:
{
"context": "SomeUnusedContextValue",
"value": [
{...}
]
}
我只关心实际响应,所以我只需要价值项。
我已经编写了以下方法来获取特定属性并将项目反序列化为对象。
public static async Task<T?> DeserializeResponse<T>(Stream str, string? property, CancellationToken ct)
{
JsonDocument jsonDocument = await JsonDocument.ParseAsync(str, default, ct).ConfigureAwait(false);
if (property is null) // some calls to the API do return data at root-level
{
return JsonSerializer.Deserialize<T>(jsonDocument.RootElement.GetRawText());
}
if (!jsonDocument.RootElement.TryGetProperty(property, out JsonElement parsed))
throw new InvalidDataException($"The specified lookup property \"{property}\" could not be found.");
return JsonSerializer.Deserialize<T>(!typeof(IEnumerable).IsAssignableFrom(typeof(T))
? parsed.EnumerateArray().FirstOrDefault().GetRawText()
: parsed.GetRawText(), new JsonSerializerOptions
{ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault });
}
问题
现在解决我的问题。有时我只需要一个对象,但是即使只有一个结果,API 仍然会返回一个数组。不是问题,因为正如在底部的 return 语句中所见,我将仅枚举数组并获取第一项(或默认的 null)。当返回的数组为空时,这似乎会崩溃,抛出以下异常:
System.InvalidOperationException: Operation is not valid due to the current state of the object.
at System.Text.Json.JsonElement.GetRawText()
at BAS.Utilities.Deserializing.ResponseDeserializer.DeserializeResponse[T](Stream str, String property, CancellationToken ct) in C:\dev\bas.api\Modules\BAS.Utilities\Deserializing\ResponseDeserializer.cs:line 40
我要序列化的对象如下:
public class JobFunctionCombination
{
/// <summary>
/// Gets or sets the combined identifier of the main function group, the function group and the sub function group.
/// </summary>
/// <example>01_0101_010101</example>
[JsonPropertyName("job_function_combination_id")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Id { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the combined names of the function groups.
/// </summary>
/// <example>Management | Human Resources | Finance controller</example>
[JsonPropertyName("description")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Description { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the identifier of the main function group.
/// </summary>
[JsonPropertyName("job_main_function_group_id")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string MainFunctionGroupId { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the identifier of the function group.
/// </summary>
[JsonPropertyName("job_function_group_id")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string FunctionGroupId { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the identifier of the sub function group.
/// </summary>
[JsonPropertyName("job_sub_function_group_id")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string SubFunctionGroupId { get; set; } = string.Empty;
}
类型和 JsonPropertyName 属性都与返回的 JSON 匹配。
尝试修复
为了尝试解决这个问题,我尝试了一些修复(其中两个您仍然可以在给定的代码示例中看到)。
- 将
JsonIgnore属性添加到类中的属性。- 我尝试将条件设置为
WhenWritingDefault和WhenWritingNull。似乎都无法解决问题。
- 我尝试将条件设置为
- 在传递给
JsonSerializer.Deserialze的JsonSerializerOptions对象中设置DefaultIgnoreCondition。- 这里我也试过
WhenWritingDefault和WhenWritingNull,也没有成功。
- 这里我也试过
- 检查
JsonElement中的数组在枚举时是否为空或使用.isNullOrEmpty()为空。- 这确实阻止了异常的发生,但是对我来说这似乎不是一个实际的修复。更像是一种 FlexTape 解决方案,只是取消了异常。
我不确定确切的问题是什么,除了JsonSerializer 显然存在空对象问题这一明确事实。我能做些什么来解决这个问题?
【问题讨论】:
标签: c# system.text.json jsonserializer jsonelement