You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Newtonsoft将JSON数字精准读取为字符串?

解决方案:用Newtonsoft保留JSON数字的原始字符串格式

问题回顾

需要实现JSON的反序列化-处理-序列化全流程,要求保留数字的原始格式(包括末尾零、科学计数法、超大整数),避免转为数值类型后丢失精度或格式变化。优先使用Newtonsoft.Json。

实现思路

核心是在反序列化阶段就保留数字的原始字符串表示,而非自动转换为数值类型。通过JsonTextReader关闭自动数值解析,再递归遍历所有JSON节点,将数值类型的节点替换为对应的字符串节点,确保原始格式完全保留。

完整代码

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;

public static class JsonNumberHelper
{
    public static JToken DeserializeNumbersAsString(string json)
    {
        using var reader = new JsonTextReader(new StringReader(json))
        {
            // 关闭浮点数自动解析以保留原始字符串;关闭日期解析避免数字被误判为日期
            FloatParseHandling = FloatParseHandling.None,
            DateParseHandling = DateParseHandling.None
        };

        var token = JToken.ReadFrom(reader);
        ReplaceNumberTokensWithStrings(token);
        return token;
    }

    private static void ReplaceNumberTokensWithStrings(JToken token)
    {
        switch (token.Type)
        {
            case JTokenType.Object:
                foreach (var property in ((JObject)token).Properties().ToList())
                {
                    ReplaceNumberTokensWithStrings(property.Value);
                }
                break;
            case JTokenType.Array:
                foreach (var item in ((JArray)token).ToList())
                {
                    ReplaceNumberTokensWithStrings(item);
                }
                break;
            case JTokenType.Integer:
            case JTokenType.Float:
                var originalNumberText = ((JValue)token).ToString(Formatting.None);
                ((JValue)token).Value = originalNumberText;
                ((JValue)token).Type = JTokenType.String;
                break;
        }
    }
}

// 测试代码
var json = """
    [{
        "foobar1": 21.37000,
        "foobar2": 0.0000000000000000001000,
        "foobar3": 1.1000E-19,
        "aReallyBigInteger" : 1111199999999999999999999999999999999911111
    }]
    """;

var processedToken = JsonNumberHelper.DeserializeNumbersAsString(json);
Console.WriteLine(processedToken.ToString(Formatting.Indented));

代码说明

  1. JsonTextReader配置:FloatParseHandling.None让浮点数以原始字符串形式读取,DateParseHandling.None避免数字被误解析为日期;
  2. 递归节点替换:遍历JSON所有节点,将整数(Integer)和浮点数(Float)类型的JValue替换为字符串类型,替换时使用节点的原始字符串表示(通过ToString(Formatting.None)获取);
  3. 格式保留:不管是末尾带零的小数、科学计数法表示的极小值,还是超出常规数值类型范围的超大整数,都能完整保留原始格式。

输出结果

运行代码后,输出将完全符合预期:

[
  {
    "foobar1": "21.37000",
    "foobar2": "0.0000000000000000001000",
    "foobar3": "1.1000E-19",
    "aReallyBigInteger": "1111199999999999999999999999999999999911111"
  }
]

内容的提问来源于stack exchange,提问作者MatteoDelOmbra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:17:10