System.Text.Json 中是否有 JRaw 的等效项
Is there an equivalent for JRaw in System.Text.Json
我正在将 ASP.NET Core 2 应用程序迁移到 ASP.NET Core 3。我的控制器需要 return 具有 属性 的对象已经是 JSON 字符串,所以它看起来像这样:
public class Thing {
public int Id { get; set; }
public string Name { get; set; }
public string Data { get; set; } // JSON Data
}
var thing = new Thing
{
Id = 1,
Name = "Thing",
Data = "{\"key\":\"value\"}"
};
Thing
应该被序列化,这样 Data
属性 就不是字符串,而是 JSON 对象的一部分。像这样:
{
"id": 1,
"name": "Thing",
"data": {
"key": "value"
}
}
在 .NET Core 2 和 Newtonsoft.Json
中,我使用 JRaw
作为 Data
的类型,因此序列化程序知道 属性 已经序列化为 JSON 并没有尝试将其表示为字符串。
.NET Core 3 使用 System.Text.Json
,与 JRaw
不兼容。有没有做同样事情的等价物?我能够使用 JsonElement
作为 Data
的类型并使用 JsonDocument.Parse(jsonString).RootElement
转换字符串。这会产生所需的结果,但我想避免不必要的反序列化+序列化步骤,因为数据对象可能相对较大。
.NET 6 引入了 Utf8JsonWriter.WriteRawValue(string json, bool skipInputValidation = false)
:
Writes the input as JSON content. It is expected that the input content is a single complete JSON value. ...
When writing untrusted JSON values, do not set skipInputValidation
to true
as this can result in invalid JSON being written, or an invalid overall payload being written to the writer instance.
因此您现在可以引入以下转换器:
/// <summary>
/// Serializes the contents of a string value as raw JSON. The string is validated as being an RFC 8259-compliant JSON payload
/// </summary>
public class RawJsonConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var doc = JsonDocument.ParseValue(ref reader);
return doc.RootElement.GetRawText();
}
protected virtual bool SkipInputValidation => false;
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) =>
// skipInputValidation : true will improve performance, but only do this if you are certain the value represents well-formed JSON!
writer.WriteRawValue(value, skipInputValidation : SkipInputValidation);
}
/// <summary>
/// Serializes the contents of a string value as raw JSON. The string is NOT validated as being an RFC 8259-compliant JSON payload
/// </summary>
public class UnsafeRawJsonConverter : RawJsonConverter
{
protected override bool SkipInputValidation => true;
}
并将您选择的转换器应用于您的数据模型:
public class Thing {
public int Id { get; set; }
public string Name { get; set; }
[JsonConverter(typeof(UnsafeRawJsonConverter))]
public string Data { get; set; } // JSON Data
}
备注:
Utf8JsonReader
似乎没有等效的方法来读取任何类型的原始值,因此仍然需要 JsonDocument
来反序列化原始 JSON值。
Utf8JsonWriter.WriteRawValue(null)
和Utf8JsonWriter.WriteRawValue("null")
生成相同的JSON,即null
。反序列化时,doc.RootElement.GetRawText()
似乎 return 两者都是空值,而不是包含标记 null
.
的字符串
您似乎很在意性能,所以我将 UnsafeRawJsonConverter
应用于您的数据模型。但是,只有在确定 Data
包含格式正确的 JSON 时,才应使用此转换器。如果不是,请使用 RawJsonConverter
:
[JsonConverter(typeof(RawJsonConverter))]
public string Data { get; set; } // JSON Data
演示 fiddle here.
我正在将 ASP.NET Core 2 应用程序迁移到 ASP.NET Core 3。我的控制器需要 return 具有 属性 的对象已经是 JSON 字符串,所以它看起来像这样:
public class Thing {
public int Id { get; set; }
public string Name { get; set; }
public string Data { get; set; } // JSON Data
}
var thing = new Thing
{
Id = 1,
Name = "Thing",
Data = "{\"key\":\"value\"}"
};
Thing
应该被序列化,这样 Data
属性 就不是字符串,而是 JSON 对象的一部分。像这样:
{
"id": 1,
"name": "Thing",
"data": {
"key": "value"
}
}
在 .NET Core 2 和 Newtonsoft.Json
中,我使用 JRaw
作为 Data
的类型,因此序列化程序知道 属性 已经序列化为 JSON 并没有尝试将其表示为字符串。
.NET Core 3 使用 System.Text.Json
,与 JRaw
不兼容。有没有做同样事情的等价物?我能够使用 JsonElement
作为 Data
的类型并使用 JsonDocument.Parse(jsonString).RootElement
转换字符串。这会产生所需的结果,但我想避免不必要的反序列化+序列化步骤,因为数据对象可能相对较大。
.NET 6 引入了 Utf8JsonWriter.WriteRawValue(string json, bool skipInputValidation = false)
:
Writes the input as JSON content. It is expected that the input content is a single complete JSON value. ...
When writing untrusted JSON values, do not set
skipInputValidation
totrue
as this can result in invalid JSON being written, or an invalid overall payload being written to the writer instance.
因此您现在可以引入以下转换器:
/// <summary>
/// Serializes the contents of a string value as raw JSON. The string is validated as being an RFC 8259-compliant JSON payload
/// </summary>
public class RawJsonConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var doc = JsonDocument.ParseValue(ref reader);
return doc.RootElement.GetRawText();
}
protected virtual bool SkipInputValidation => false;
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) =>
// skipInputValidation : true will improve performance, but only do this if you are certain the value represents well-formed JSON!
writer.WriteRawValue(value, skipInputValidation : SkipInputValidation);
}
/// <summary>
/// Serializes the contents of a string value as raw JSON. The string is NOT validated as being an RFC 8259-compliant JSON payload
/// </summary>
public class UnsafeRawJsonConverter : RawJsonConverter
{
protected override bool SkipInputValidation => true;
}
并将您选择的转换器应用于您的数据模型:
public class Thing {
public int Id { get; set; }
public string Name { get; set; }
[JsonConverter(typeof(UnsafeRawJsonConverter))]
public string Data { get; set; } // JSON Data
}
备注:
Utf8JsonReader
似乎没有等效的方法来读取任何类型的原始值,因此仍然需要JsonDocument
来反序列化原始 JSON值。
的字符串Utf8JsonWriter.WriteRawValue(null)
和Utf8JsonWriter.WriteRawValue("null")
生成相同的JSON,即null
。反序列化时,doc.RootElement.GetRawText()
似乎 return 两者都是空值,而不是包含标记null
.您似乎很在意性能,所以我将
UnsafeRawJsonConverter
应用于您的数据模型。但是,只有在确定Data
包含格式正确的 JSON 时,才应使用此转换器。如果不是,请使用RawJsonConverter
:[JsonConverter(typeof(RawJsonConverter))] public string Data { get; set; } // JSON Data
演示 fiddle here.