-1

在 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': ',!!!'。是否有一种通用的方法可以以编程方式转义特殊字符,以便我可以处理所有组合?

4

2 回答 2

0

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

它需要看起来像这样:

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

如果您对 json 转义序列有进一步的疑问,请尝试查看以下内容:

如何在构建 JSON 字符串时转义特殊字符?

如果当您说“转义特殊字符”时您真正在谈论的是如何在 JPath 中执行通配符表达式(我之所以怀疑是因为您列出了一堆 !! 结尾模式),那么您可能会尝试这样的事情:

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

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

于 2019-03-15T19:11:42.757 回答
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);

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

于 2019-03-15T19:10:14.537 回答