如何在C#中读取json时以编程方式转义特殊字符?

时间:2019-03-15 17:10:26

标签: c# json json.net jpath

在json消息中,我有一个Name字段,可以包含不同特殊字符的各种组合。由于特殊字符,当我过滤此属性时,出现错误:

  

解析路径查询时出现意外字符:!

此属性的值不固定。由于特殊字符的组合是未知的,因此在应用jpath过滤属性时,我无法应用特定的转义序列。

例如:如果'Name': ''!!!',$..[?(@Name== '\'!!!')]将解决问题。但是,同一字段也可以具有类似'Name': 'A!!!'的值。在这种情况下,相同的转义序列将失败。

 [Test]
    public static void Test()
    {
        string json = @"{'Type': 'Contoso',
             'Products': [
                 {
                 'Name': ''!!!',
                 'Price': 99.95
                 }]
                    }";
        var jobject = JToken.Parse(json);
        string name = (string) jobject.SelectToken("$..[?(@Name== ''!!!')]");

    }

Name的其他可能组合是'Name': '!"!!''Name': ''"!!''Name': '$"!!''Name': '/"!!' 'Name': ',!!!'等。 是否有一种通用的方式可以通过编程方式转义特殊字符,以便我可以处理所有组合?

2 个答案:

答案 0 :(得分:0)

这应该自动转义未转义的撇号。如果JSON包含多个未转义的撇号,则应递归进行操作,直到所有这些都被修复为止。

但是,实际上,您应该联系生成不良JSON的任何人,并要求他们进行更正。

private static JToken ParseWithAutoEscape(string json)
{
    try
    {
        return JToken.Parse(json);
    }
    catch (JsonReaderException ex)
    {
        if (!ex.Message.StartsWith("After parsing a value an unexpected character was encountered:"))
            throw;

        var lines = json.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        var badLine = lines[ex.LineNumber - 1];

        // contains the part of the line before the apostrophe
        var before = badLine.Substring(0, ex.LinePosition - 1);

        // contains the apostrophe and what comes after.
        var after = badLine.Substring(ex.LinePosition - 1);

        lines[ex.LineNumber - 1] = $"{before}\\{after}";
        json = String.Join("\n", lines);

        // try again.
        return ParseWithAutoEscape(json);
    }
}

用法:

var jobject = ParseWithAutoEscape(json);
var name = jobject.SelectToken("$..[?(@Name== '\\'!!!')]");
Debug.WriteLine(name);

请注意,'也需要在查询选择器中转义。

答案 1 :(得分:0)

就像艾米所说,json(字符串json)是问题,而不是您的jpath表达式。由于'Name': ''!!!'是无效的json,因此它包含无效的json。您需要将单引号转义到\'

它应该看起来像这样:

    string json = @"{'Type': 'Contoso',
         'Products': [
             {
             'Name': '\'!!!',
             'Price': 99.95
             }]
                }";

如果您对json转义序列有更多疑问,请尝试看一下:

How to escape special characters in building a JSON string?

如果您说“转义特殊字符”时真正在说的是如何在JPath中执行通配符表达式(我很怀疑,因为您列出了一堆!!-end模式),那么您可以尝试类似这个:

    string json = @"{'Type': 'Contoso',
         'Products': [
             {
             'Name': '\'!!!',
             'Price': 99.95
             }]
                }";
    var jobject = JObject.Parse(json);
    string name = (string)jobject.SelectToken("$.Products[?(@.Name =~ /.*!!$/i)].Name");

它将匹配JavaScript正则表达式,任何以!!结尾的名称! (两个感叹号)。