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

C#中如何还原Azure SQL数据库中转义双大括号的JSON数据

解决Azure SQL中转义双大括号JSON的解析问题

这个场景确实很头疼——直接全局替换{{和}}虽然简单,但很容易误伤字符串内容里的合法双大括号(比如如果某个字段值是"{{VIP}} Customer",替换后就会变成"{VIP} Customer",完全破坏了原始数据)。不过用Newtonsoft.Json的话,我们可以通过自定义解析逻辑,精准区分JSON语法层面的双大括号和字符串值内部的双大括号,完美解决这个问题。

核心思路

我们需要写一个自定义的TextReader包装器,它会在读取字符流时:

  1. 跟踪当前是否处于JSON的字符串值内部(通过检测双引号切换状态)
  2. 仅在非字符串的语法区域,把连续的{{替换为单个{,}}替换为单个}
  3. 字符串内部的双大括号保持原样,不做修改

实现代码

首先定义自定义的Reader类:

using Newtonsoft.Json;
using System.IO;

public class DoubleBracketJsonReader : TextReader
{
    private readonly TextReader _innerReader;
    private bool _inString;
    private char? _pendingChar;

    public DoubleBracketJsonReader(TextReader innerReader)
    {
        _innerReader = innerReader;
    }

    public override int Read()
    {
        // 先处理上次遗留的字符
        if (_pendingChar.HasValue)
        {
            var c = _pendingChar.Value;
            _pendingChar = null;
            return c;
        }

        var currentInt = _innerReader.Read();
        if (currentInt == -1) return -1;
        
        char currentChar = (char)currentInt;

        // 切换字符串状态(遇到双引号时)
        if (currentChar == '"')
        {
            _inString = !_inString;
            return currentInt;
        }

        // 仅在非字符串区域处理双大括号
        if (!_inString)
        {
            if (currentChar == '{')
            {
                var nextInt = _innerReader.Read();
                if (nextInt == -1) return currentInt;
                
                char nextChar = (char)nextInt;
                if (nextChar == '{')
                {
                    // 遇到{{,返回单个{
                    return '{';
                }
                else
                {
                    // 不是连续的{,把下一个字符存起来下次返回
                    _pendingChar = nextChar;
                    return currentInt;
                }
            }
            else if (currentChar == '}')
            {
                var nextInt = _innerReader.Read();
                if (nextInt == -1) return currentInt;
                
                char nextChar = (char)nextInt;
                if (nextChar == '}')
                {
                    // 遇到}},返回单个}
                    return '}';
                }
                else
                {
                    _pendingChar = nextChar;
                    return currentInt;
                }
            }
        }

        // 其他情况直接返回原字符
        return currentInt;
    }
}

然后用这个Reader来解析你的转义JSON:

// 从Azure SQL读取的转义JSON字符串
var escapedJson = "{{\"Id\":10,\"Title\":\"Account Data\",\"Date\":\"0001-01-01T00:00:00.000Z\",\"Data\":{{\"Id\":22,\"Name\":\"My Object\"}}}}";

// 使用自定义Reader解析
using var stringReader = new StringReader(escapedJson);
using var customReader = new DoubleBracketJsonReader(stringReader);
var parsedObject = JsonConvert.DeserializeObject<JObject>(customReader);

// 输出格式化后的合法JSON
Console.WriteLine(parsedObject.ToString(Formatting.Indented));

为什么这个方案可靠?

  • 精准区分场景:只有当双大括号出现在JSON的语法位置(比如对象/数组的开头结尾)时才会替换,字符串内部的双大括号完全保留。
  • 无需修改存储:直接在读取解析环节处理,完全不影响Azure SQL里的原始数据。
  • 兼容复杂JSON:即使嵌套多层对象,或者字符串里包含特殊字符,都能正确解析。

额外说明

如果你的双大括号是因为双重序列化导致的(比如先把对象序列化为JSON字符串,然后又把这个字符串再次序列化,导致{被转义为\{,但存储时丢失了反斜杠变成{{),也可以用这个方案处理——本质上它解决的是同一个解析问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:16:05