问题描述
我有一个具有 JObject
类型属性的 DTO 类。此 DTO 类在多个服务之间通过 HTTP 发送/接收。使用 JObject 是因为 ExtractedData
没有预定义的属性
public class MyDTO
{
public JObject ExtractedData {get;set;}
}
我正在将此项目转换为 .NET 5。什么与 .NET 5 中的 JObject 等效?我试图避免 JsonDocument 因为(来自 docs):
JsonDocument 将数据的内存视图构建到一个池中 缓冲。因此,与 Newtonsoft.Json 中的 JObject 或 JArray 不同, JsonDocument 类型实现了 IDisposable 并且需要在一个 使用块。
我打算使用 JsonElement
。这是最合适的选择还是有任何其他类型可用于将 JSON 作为对象保存?
解决方法
与 JObject
最接近的等价物确实是 JsonElement
,因此您可以按如下方式修改您的 DTO:
public class MyDTO
{
public JsonElement ExtractedData {get;set;}
}
无需担心处理任何文档,因为在内部,JsonElementConverter
使用的 JsonSerializer
返回非池化元素(通过在 .NET 5 中克隆该元素)。>
但是,对应关系并不准确,因此请记住以下几点:
-
JsonElement
代表任何 JSON 值,因此最接近于JToken
而不是JObject
。由于JsonElement
是struct
,因此没有对应于 JSON 对象的子类。如果要将ExtractedData
限制为 JSON 对象,则需要在 setter 中检查:public class MyDTO { JsonElement extractedData; public JsonElement ExtractedData { get => extractedData; set { if (value.ValueKind != JsonValueKind.Object // && value.ValueKind != JsonValueKind.Null Uncomment if you want to allow null ) throw new ArgumentException(string.Format("{0} is not a JSON object type",value.ValueKind)); extractedData = value; } } }
-
由于
JsonElement
是结构体,因此默认值不是null
。那么,它是什么?事实证明default(JsonElement)
有ValueKind = JsonValueKind.Undefined
:没有值(与 Null 不同)。
如果您尝试使用
JsonElement
序列化此类默认JsonSerializer
,则会引发异常。 IE。如果你只是这样做var json = JsonSerializer.Serialize(new MyDTO());
然后抛出一个
System.InvalidOperationException: Operation is not valid due to the current state of the object.
异常。您有几个选择可以避免这个问题:
-
在 .NET 5 中,您可以像这样应用
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
:public class MyDTO { [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public JsonElement ExtractedData {get;set;} }
这会导致在序列化期间跳过
ExtractedData
的未初始化值。 -
在 .NET Core 3.x 中,
JsonIgnoreCondition
不存在,因此您可以将ExtractedData
定义为可以为空:public class MyDTO { public JsonElement? ExtractedData {get;set;} }
或者您可以像这样将其初始化为 null
JsonElement
:public class MyDTO { public JsonElement ExtractedData {get;set;} = JsonExtensions.Null; } public static class JsonExtensions { static readonly JsonElement nullElement = CreateNull(); public static JsonElement Null => nullElement; static JsonElement CreateNull() { using var doc = JsonDocument.Parse("null"); return doc.RootElement.Clone(); } }
这两个选项都会导致
ExtractedData
的未初始化值序列化为null
。
-
-
另见相关问题: