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

如何在C# 7中递归遍历JSON文档并对所有数值类型执行取整操作?

解决JSON递归数值取整问题

一、基于JsonDocument的递归实现(兼容C#7)

你的现有代码仅处理了两层对象结构,要实现全层级递归遍历,需编写递归方法处理所有类型的JsonElement(对象、数组、数字等)。以下是完整实现:

核心递归处理方法

private static void ProcessJsonElement(JsonElement element, Utf8JsonWriter writer, int roundDigits)
{
    switch (element.ValueKind)
    {
        case JsonValueKind.Object:
            writer.WriteStartObject();
            foreach (var property in element.EnumerateObject())
            {
                writer.WritePropertyName(property.Name);
                ProcessJsonElement(property.Value, writer, roundDigits);
            }
            writer.WriteEndObject();
            break;
        case JsonValueKind.Array:
            writer.WriteStartArray();
            foreach (var item in element.EnumerateArray())
            {
                ProcessJsonElement(item, writer, roundDigits);
            }
            writer.WriteEndArray();
            break;
        case JsonValueKind.Number:
            // 执行Math.Round取整,同时兼容不同数字类型
            if (element.TryGetDouble(out double value))
            {
                var roundedValue = Math.Round(value, roundDigits);
                // 自动判断是否保留小数位,避免整数显示为带.0的浮点数
                if (roundedValue == (int)roundedValue)
                {
                    writer.WriteNumberValue((int)roundedValue);
                }
                else
                {
                    writer.WriteNumberValue(roundedValue);
                }
            }
            else
            {
                // 处理无法转换为double的超大整数,直接保留原始值避免精度丢失
                element.WriteTo(writer);
            }
            break;
        default:
            // 字符串、布尔值、null等类型直接原样写入
            element.WriteTo(writer);
            break;
    }
}

调用递归方法的主函数

修改原有方法,支持根节点为对象或数组,同时调用递归逻辑:

public static string ApplyRounding(string originalJson, int roundDigits = 15)
{
    using var ms = new MemoryStream();
    using var writer = new Utf8JsonWriter(ms, new JsonWriterOptions { Indented = false, SkipValidation = true });
    
    using var jsonDocument = JsonDocument.Parse(originalJson);
    var root = jsonDocument.RootElement;
    
    ProcessJsonElement(root, writer, roundDigits);
    
    writer.Flush();
    return Encoding.UTF8.GetString(ms.ToArray());
}

关键特性

  • 递归遍历JSON所有层级,包括嵌套对象、数组内的数字
  • 智能处理数字格式,整数不会被强制转为浮点数
  • 兼容超大整数场景,避免精度丢失

二、关于JsonNode的说明

你提到的JsonNode是.NET 6及以上版本才引入的API,而C#7对应的.NET版本(如.NET Core 2.x、.NET Framework 4.x)并不支持该类型。若你的项目可以升级到.NET 6+(建议同步升级C#到10+),可以使用更直观的原地修改方案:

public static string ApplyRoundingWithJsonNode(string originalJson, int roundDigits = 15)
{
    var node = JsonNode.Parse(originalJson);
    ProcessJsonNode(node, roundDigits);
    return node.ToJsonString(new JsonSerializerOptions { WriteIndented = false });
}

private static void ProcessJsonNode(JsonNode node, int roundDigits)
{
    switch (node)
    {
        case JsonObject obj:
            // 转为List避免遍历中修改集合引发异常
            foreach (var property in obj.ToList())
            {
                ProcessJsonNode(property.Value, roundDigits);
            }
            break;
        case JsonArray array:
            for (int i = 0; i < array.Count; i++)
            {
                ProcessJsonNode(array[i], roundDigits);
            }
            break;
        case JsonValue value when value.ValueKind == JsonValueKind.Number:
            if (value.TryGetValue<double>(out double num))
            {
                var rounded = Math.Round(num, roundDigits);
                // 替换原节点值,自动适配整数/浮点数格式
                if (rounded == (int)rounded)
                {
                    value.ReplaceWith((int)rounded);
                }
                else
                {
                    value.ReplaceWith(rounded);
                }
            }
            break;
        // 其他类型无需处理
    }
}

说明

  • JsonNode支持原地修改JSON结构,代码逻辑更简洁直观
  • 仅适用于.NET 6及以上版本的项目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:15:39