我有一个 DTO 类,它具有 JObject 类型的属性.此 DTO 类在多个服务之间通过 HTTP 发送/接收.使用 JObject 是因为 ExtractedData 没有预定义的属性
I have DTO class that has a property of type JObject. This DTO class is send/receive over HTTP between multiple services. JObject is used because the ExtractedData does not have predefined properties
public class MyDTO { public JObject ExtractedData {get;set;} }我正在将此项目转换为 .NET 5.什么与 .NET 5 中的 JObject 等效?我试图避免 JsonDocument 因为(来自 文档):
I am converting this project to .NET 5. What is equivalent to JObject in .NET 5? I am trying to avoid JsonDocument because (from the docs):
JsonDocument 将数据的内存视图构建到一个池中缓冲.因此,与 Newtonsoft.Json 中的 JObject 或 JArray 不同,JsonDocument 类型实现了 IDisposable 并且需要在一个内部使用使用块.
JsonDocument builds an in-memory view of the data into a pooled buffer. Therefore, unlike JObject or JArray from Newtonsoft.Json, the JsonDocument type implements IDisposable and needs to be used inside a using block.
我打算使用 JsonElement.这是最合适的选择还是有任何其他类型可用于将 JSON 作为对象保存?
I am planing to use JsonElement. Is this the most appropriate choice or is there any other type available to hold JSON as an object?
推荐答案最接近于 JObject 确实是 JsonElement 这样你就可以修改你的 DTO 如下:
The closest equivalent to JObject is indeed JsonElement so you could modify your DTO as follows:
public class MyDTO { public JsonElement ExtractedData {get;set;} }无需担心在内部将任何文档处理为 JsonElementConverter.microsoft/en-us/dotnet/api/system.text.json.jsonserializer" rel="noreferrer">JsonSerializer 返回一个非池化元素(通过克隆元素在 .NET 5 中).
There is no need to worry about disposing of any documents as, internally, the JsonElementConverter used by JsonSerializer returns a non-pooled element (by cloning the element in .NET 5).
但是,对应关系并不准确,因此请记住以下几点:
However, the correspondence is not exact, so keep the following in mind:
JsonElement 代表任何 JSON 值,因此最接近于 JToken 不是 JObject.由于 JsonElement 是一个 struct,因此没有对应于 JSON 对象的子类.如果要将 ExtractedData 限制为 JSON 对象,则需要在 setter 中检查:
JsonElement represents any JSON value and thus corresponds most closely to JToken not JObject. As JsonElement is a struct there is no subclass corresponding to a JSON object. If you want to constrain ExtractedData to be a JSON object you will need to check this in the 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:
Since JsonElement is a struct, the default value is not null. So, what is it? It turns out that default(JsonElement) has ValueKind = JsonValueKind.Undefined:
没有值(与 Null 不同).
There is no value (as distinct from Null).
如果您尝试使用 JsonSerializer 序列化此类默认 JsonElement,则会引发异常.IE.如果你只是这样做
If you attempt to serialize such a default JsonElement with JsonSerializer, an exception will be thrown. I.e. if you simply do
var json = JsonSerializer.Serialize(new MyDTO());然后一个 System.InvalidOperationException: Operation is not valid due to the current state of the object. 异常被抛出.
Then a System.InvalidOperationException: Operation is not valid due to the current state of the object. exception is thrown.
您有几个选择可以避免这个问题:
You have a few options to avoid this problem:
在 .NET 5 中,您可以应用 [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 像这样:
这会导致在序列化期间跳过 ExtractedData 的未初始化值.
This causes uninitialized values of ExtractedData to be skipped during serialization.
在 .NET Core 3.x 中 JsonIgnoreCondition 不存在,因此您可以将 ExtractedData 定义为可以为空:
In .NET Core 3.x JsonIgnoreCondition does not exist, so you could instead define ExtractedData to be nullable:
public class MyDTO { public JsonElement? ExtractedData {get;set;} }或者您可以像这样将其初始化为空 JsonElement:
Or you could initialize it to a null JsonElement like so:
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.
Both options cause uninitialized values of ExtractedData to serialize as null.
另见相关问题:
- 在 core 3 中将 newtonsoft 代码转换为 System.Text.Json.JObject.Parse 和 JsonProperty 的等价物.
- 由于对象 (System.Text.Json) 的当前状态,操作无效.
更多推荐
System.Text.Json 中 JObject 的等效项
发布评论