6

我正在BigInteger使用以下方法将 a 序列化为 JSON System.Text.Json

JsonSerializer.Serialize(new {foo = new BigInteger(ulong.MaxValue) + 1})

这导致以下输出:

{"foo":{"IsPowerOfTwo":true,"IsZero":false,"IsOne":false,"IsEven":true,"Sign":1}}

如果我添加一个将BigInteger值转换为a 的转换器ulong,它当然会失败,因为BigInteger值太大:

var options = new JsonSerializerOptions();
options.Converters.Add(new BigIntegerConverter());
JsonSerializer.Serialize(new {foo = new BigInteger(ulong.MaxValue) + 1}, options);

这是转换器:

public class BigIntegerConverter : JsonConverter<BigInteger>
{
    public override BigInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException();

    public override void Write(Utf8JsonWriter writer, BigInteger value, JsonSerializerOptions options) => writer.WriteNumberValue((ulong)value);
}

我想要的输出是:

{"foo":18446744073709551616}

我知道这可以JsonWriter.WriteRawValue在 Json.NET 中实现,但我仅限于使用System.Text.Json.

有没有办法在不手动破解序列化字符串的情况下做到这一点?

4

1 回答 1

4

为 for 编写转换器BigInteger有点尴尬,因为正如您所指出的,Utf8JsonReader并且Utf8JsonWriter不提供从 .NET 5 开始读取和写入原始 JSON 的能力。

JsonDocument但是,确实通过 提供了对原始 JSON 的访问RootElement.GetRawText(),因此您可以通过读取和写入中间文档来编写转换器,如下所示:

public class BigIntegerConverter : JsonConverter<BigInteger>
{
    public override BigInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.Number)
            throw new JsonException(string.Format("Found token {0} but expected token {1}", reader.TokenType, JsonTokenType.Number ));
        using var doc = JsonDocument.ParseValue(ref reader);
        return BigInteger.Parse(doc.RootElement.GetRawText(), NumberFormatInfo.InvariantInfo);
    }

    public override void Write(Utf8JsonWriter writer, BigInteger value, JsonSerializerOptions options)
    {
        var s = value.ToString(NumberFormatInfo.InvariantInfo);
        using var doc = JsonDocument.Parse(s);
        doc.WriteTo(writer);
    }
}

演示小提琴在这里

于 2020-12-18T02:03:58.870 回答