9

我有一些包含注释的 JSON(即使JSON 规范中不严格允许注释。)如何使用 解析这个 JSON System.Text.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)

如何使用 解析或反序列化此 JSON System.Text.Json

4

1 回答 1

16

可以解析包含注释的 JSON System.Text.Json,但默认情况下,此类 JSON 被视为无效,可能是因为JSON 标准中不包含注释。尽管如此,可以通过修改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.CommentHandlingUtf8JsonReader

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;
}

使用JsonDocumentset解析时JsonDocumentOptions.CommentHandling = JsonCommentHandling.Skip

var options = new JsonDocumentOptions
{
    CommentHandling = JsonCommentHandling.Skip,
};
using var doc = JsonDocument.Parse(jsonString, options);

使用JsonSerializerset反序列化时JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip

var options = new JsonSerializerOptions
{
    ReadCommentHandling = JsonCommentHandling.Skip
};
var person = JsonSerializer.Deserialize<Person>(jsonString, options);

请注意,从 .NET Core 3.1 开始,JsonDocumentJsonSerializer支持跳过或禁止注释;他们不支持加载它们。如果您尝试设置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 相比,它简化了注释处理,其中注释暴露在ReadJson()每次读取令牌时都必须检查。)

有关更多信息,请参阅如何在 .NET 中序列化和反序列化 JSON:允许注释和尾随逗号

演示小提琴在这里

于 2019-12-22T19:00:00.027 回答