使用System.Text.Json序列化BigInteger

7

我正在使用System.Text.Json将一个BigInteger序列化为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。有没有不需要手动篡改序列化字符串的方法来实现这个呢?
1个回答

6
在 .NET 6 中,新增了直接编写原始值的方法:Utf8JsonWriter.WriteRawValue()。因此,BigIntegerConverter 现在可以编写如下:
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) =>
        writer.WriteRawValue(value.ToString(NumberFormatInfo.InvariantInfo), false);
}

注意:

在 .NET 5 及更早版本中,编写 BigInteger 转换器有些棘手,因为如您所见,Utf8JsonReaderUtf8JsonWriter 不提供读取和写入原始 JSON 的功能。取而代之,可以使用中间的JsonDocument来读写任意 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);
    }
}

这里的演示fiddle 链接.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接