我有一些包含注释的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?
答案 0 :(得分:4)
JSON可以由System.Text.Json
进行解析,但默认情况下此类JSON被认为无效,这可能是因为注释未包含在JSON standard中。不过,可以通过修改选项中的 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
直接阅读时启用跳过或加载注释,请在JsonReaderOptions.CommentHandling
之一中设置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()
方法时不需要手动跳过注释,这与Newtonsoft相比,简化了注释处理,在Newtonsoft中,注释ReadJson()
公开并且每次都要检查令牌被读取。)
有关更多信息,请参见 How to serialize and deserialize JSON in .NET : Allow comments and trailing commas 。
演示小提琴here。