使用System.Text.Json序列化BigInteger

问题描述

我正在使用BigIntegerSystem.Text.Json序列化为JSON:

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

这将产生以下输出:

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

如果我添加一个将BigInteger值转换为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}

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

有什么方法可以做到,而无需手动破解序列化的字符串?

解决方法

BigInteger写一个转换器有点尴尬,因为您注意到,Utf8JsonReaderUtf8JsonWriter在.NET 5中不提供读写原始JSON的能力。

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

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

演示小提琴here

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...