如何使用 System.Text.Json 解析带有注释的 JSON?
How can I parse JSON with comments using System.Text.Json?
我有一些包含注释的 JSON(尽管 JSON spec 中严格不允许注释。)如何使用 System.Text.Json
解析此 JSON ?
我收到的JSON如下:
// A person
{
"Id" : 1 /* Person's ID */,
"Name" : "Foo" // Person's name
}
当我尝试将其加载到 JsonDocument
中时:
using var doc = JsonDocument.Parse(jsonString);
我得到以下异常:
System.Text.Json.JsonReaderException: '/' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.
at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)```
当我尝试使用 JsonSerializer
反序列化时:
var person = JsonSerializer.Deserialize<Person>(jsonString);
我遇到类似的异常:
System.Text.Json.JsonException: '/' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
---> System.Text.Json.JsonReaderException: '/' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.
at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)
如何用 System.Text.Json
解析或反序列化此 JSON?
JSON 包含评论可以被 System.Text.Json
解析,但是 默认情况下这样的 JSON 被认为是无效的 ,可能是因为评论不是包含在选项中的 JSON standard. Support for comments nevertheless can be enabled by modifying the JsonCommentHandling
枚举中:
Disallow 0 Doesn't allow comments within the JSON input.
Comments are treated as invalid JSON if found, and a JsonException is thrown.
This is the default value.
Skip 1 Allows comments within the JSON input and ignores them.
The Utf8JsonReader behaves as if no comments are present.
Allow 2 Allows comments within the JSON input and treats them as valid tokens.
While reading, the caller can access the comment values.
在使用 Utf8JsonReader
, set JsonReaderOptions.CommentHandling
in one of the Utf8JsonReader
constructors 直接阅读时允许跳过或加载评论,例如如下:
static List<string> GetComments(string jsonString)
{
var options = new JsonReaderOptions
{
CommentHandling = JsonCommentHandling.Allow
};
var list = new List<string>();
var reader = new Utf8JsonReader(new ReadOnlySpan<byte>(Encoding.UTF8.GetBytes(jsonString)), options);
while (reader.Read())
if (reader.TokenType == JsonTokenType.Comment)
list.Add(reader.GetComment());
return list;
}
用JsonDocument
解析时设置JsonDocumentOptions.CommentHandling = JsonCommentHandling.Skip
:
var options = new JsonDocumentOptions
{
CommentHandling = JsonCommentHandling.Skip,
};
using var doc = JsonDocument.Parse(jsonString, options);
使用 JsonSerializer
反序列化时设置 JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip
:
var options = new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip
};
var person = JsonSerializer.Deserialize<Person>(jsonString, options);
请注意,从 .NET Core 3.1 开始,JsonDocument
和 JsonSerializer
仅支持跳过或禁止评论;他们不支持加载它们。如果您尝试为其中任何一个设置 JsonCommentHandling.Allow
,您将得到一个异常:
System.ArgumentOutOfRangeException: Comments cannot be stored in a JsonDocument, only the Skip and Disallow comment handling modes are supported. (Parameter 'value')
System.ArgumentOutOfRangeException: Comments cannot be stored when deserializing objects, only the Skip and Disallow comment handling modes are supported. (Parameter 'value')
(这意味着写 JsonConverter<T>.Read()
method, which simplifies comment processing as compared to Newtonsoft where comments are exposed to ReadJson()
时不需要手动跳过注释,每次读取标记时都必须检查。)
有关更多信息,请参阅 How to serialize and deserialize JSON in .NET : Allow comments and trailing commas。
演示 fiddle here.
我有一些包含注释的 JSON(尽管 JSON spec 中严格不允许注释。)如何使用 System.Text.Json
解析此 JSON ?
我收到的JSON如下:
// A person
{
"Id" : 1 /* Person's ID */,
"Name" : "Foo" // Person's name
}
当我尝试将其加载到 JsonDocument
中时:
using var doc = JsonDocument.Parse(jsonString);
我得到以下异常:
System.Text.Json.JsonReaderException: '/' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0. at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes) at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)```
当我尝试使用 JsonSerializer
反序列化时:
var person = JsonSerializer.Deserialize<Person>(jsonString);
我遇到类似的异常:
System.Text.Json.JsonException: '/' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0. ---> System.Text.Json.JsonReaderException: '/' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0. at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes) at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)
如何用 System.Text.Json
解析或反序列化此 JSON?
JSON 包含评论可以被 System.Text.Json
解析,但是 默认情况下这样的 JSON 被认为是无效的 ,可能是因为评论不是包含在选项中的 JSON standard. Support for comments nevertheless can be enabled by modifying the JsonCommentHandling
枚举中:
Disallow 0 Doesn't allow comments within the JSON input. Comments are treated as invalid JSON if found, and a JsonException is thrown. This is the default value. Skip 1 Allows comments within the JSON input and ignores them. The Utf8JsonReader behaves as if no comments are present. Allow 2 Allows comments within the JSON input and treats them as valid tokens. While reading, the caller can access the comment values.
在使用 Utf8JsonReader
, set JsonReaderOptions.CommentHandling
in one of the Utf8JsonReader
constructors 直接阅读时允许跳过或加载评论,例如如下:
static List<string> GetComments(string jsonString)
{
var options = new JsonReaderOptions
{
CommentHandling = JsonCommentHandling.Allow
};
var list = new List<string>();
var reader = new Utf8JsonReader(new ReadOnlySpan<byte>(Encoding.UTF8.GetBytes(jsonString)), options);
while (reader.Read())
if (reader.TokenType == JsonTokenType.Comment)
list.Add(reader.GetComment());
return list;
}
用JsonDocument
解析时设置JsonDocumentOptions.CommentHandling = JsonCommentHandling.Skip
:
var options = new JsonDocumentOptions
{
CommentHandling = JsonCommentHandling.Skip,
};
using var doc = JsonDocument.Parse(jsonString, options);
使用 JsonSerializer
反序列化时设置 JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip
:
var options = new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip
};
var person = JsonSerializer.Deserialize<Person>(jsonString, options);
请注意,从 .NET Core 3.1 开始,JsonDocument
和 JsonSerializer
仅支持跳过或禁止评论;他们不支持加载它们。如果您尝试为其中任何一个设置 JsonCommentHandling.Allow
,您将得到一个异常:
System.ArgumentOutOfRangeException: Comments cannot be stored in a JsonDocument, only the Skip and Disallow comment handling modes are supported. (Parameter 'value') System.ArgumentOutOfRangeException: Comments cannot be stored when deserializing objects, only the Skip and Disallow comment handling modes are supported. (Parameter 'value')
(这意味着写 JsonConverter<T>.Read()
method, which simplifies comment processing as compared to Newtonsoft where comments are exposed to ReadJson()
时不需要手动跳过注释,每次读取标记时都必须检查。)
有关更多信息,请参阅 How to serialize and deserialize JSON in .NET : Allow comments and trailing commas。
演示 fiddle here.