如何用Newtonsoft.Json反序列化含正则转义的JSON正则数组
问题:类JSON格式正则数组反序列化失败
我在数据库单个字段中存储了类JSON格式的正则表达式数组,示例为:["^.*\/Car($|\/$|\?|\/\?)"]。使用Newtonsoft.Json将其反序列化为string[]对象时,始终抛出Newtonsoft.Json.JsonReaderException。
测试代码
public static void Main(string[] args) { // 正常工作的示例 string patterns = @"[""^.*\/Car""]"; var x = JsonConvert.DeserializeObject<string[]>(patterns); Console.WriteLine(x.First()); // 输出 ^.*/Car // 报错示例:正则中的\?导致JSON解析失败 patterns = @"[""^.*\/Car\?""]"; x = JsonConvert.DeserializeObject<string[]>(patterns); // 抛出Newtonsoft.Json.JsonReaderException: 'Bad JSON escape sequence: \?. Path '', line 1, position 12.' Console.WriteLine(x.First()); // 报错示例:JsonEncodedText.Encode无效 patterns = @"[""^.*\/Car\?""]"; x = JsonConvert.DeserializeObject<string[]>(JsonEncodedText.Encode(patterns).ToString()); // 抛出Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: \. Path '', line 1, position 2.' Console.WriteLine(x.First()); // 正常工作的示例:将\?转义为\\? patterns = @"[""^.*\/Car\\?""]"; x = JsonConvert.DeserializeObject<string[]>(patterns); // 输出 .*/Car\? Console.WriteLine(x.First()); // 最终需要解决的场景 // 正则表达式为 ^.*\/Car($|\/$|\?|\/\?) patterns = @"[""^.*\/Car($|\/$|\?|\/\?)"]"; x = JsonConvert.DeserializeObject<string[]>(patterns); // 抛出异常 Console.WriteLine(x.First()); }
问题原因
核心冲突是JSON转义规则与正则转义规则不兼容:
- JSON仅允许特定的转义序列(如
\"、\\、\/等),\?不属于JSON合法转义,直接解析会触发错误; - 数据库中存储的内容本质是不符合标准JSON规范的字符串——正则中的反斜杠未按照JSON要求转义为
\\。
解决方案:预处理字符串修复JSON格式
由于无法修改数据库存储,必须先将非法的转义序列修正为JSON合法格式,再执行反序列化。
基础修复方案
直接将字符串中所有单个反斜杠替换为两个反斜杠,确保JSON解析器能正确识别:
public static void Main(string[] args) { // 从数据库读取的原始类JSON字符串 string rawPatterns = @"[""^.*\/Car($|\/$|\?|\/\?)"]"; // 预处理:修复JSON转义,将单个\替换为\\ string fixedJson = rawPatterns.Replace(@"\", @"\\"); // 正常反序列化 var regexArray = JsonConvert.DeserializeObject<string[]>(fixedJson); Console.WriteLine(regexArray.First()); // 输出 ^.*\/Car($|\/$|\?|\/\?) }
精准修复方案(避免破坏合法JSON转义)
如果原始字符串中存在JSON合法转义(如\"表示双引号),直接全局替换会破坏这些合法序列。此时可以用正则表达式只替换非法的转义序列:
public static void Main(string[] args) { string rawPatterns = @"[""^.*\/Car($|\/$|\?|\/\?)"]"; // 正则替换:仅修复非JSON标准的转义序列 // 匹配规则:单个反斜杠,且后面不是JSON允许的转义字符("、\、/、b、f、n、r、t、u) string fixedJson = Regex.Replace(rawPatterns, @"(?<!\\)\\(?![""\\/bfnrtu])", @"\\"); var regexArray = JsonConvert.DeserializeObject<string[]>(fixedJson); Console.WriteLine(regexArray.First()); }
为什么之前的方法无效?
JsonEncodedText.Encode():该方法是将普通.NET字符串编码为JSON格式,但你传入的是已经错误格式化的类JSON字符串,它会把整个内容当作普通文本再次转义,导致格式彻底混乱;Regex.Escape():该方法用于转义正则表达式的特殊字符,和JSON转义规则无关,无法解决JSON解析错误。
内容的提问来源于stack exchange,提问作者josibu
相关产品推荐
相关产品推荐

