在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': ',!!!'
等。
是否有一种通用的方式可以通过编程方式转义特殊字符,以便我可以处理所有组合?
答案 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正则表达式,任何以!!结尾的名称! (两个感叹号)。