您遇到的问题是 C# 版本的 JsonPath 不包含 Json 解析器,因此您必须将它与另一个处理序列化和反序列化的 Json 框架一起使用。
JsonPath 的工作方式是使用一个名为IJsonPathValueSystem 的接口来遍历解析后的Json 对象。 JsonPath 自带了一个内置的BasicValueSystem,使用IDictionary 接口表示Json 对象,使用IList 接口表示Json 数组。
您可以通过使用 C# 集合初始化器构造它们来创建自己的 BasicValueSystem 兼容的 Json 对象,但是当您的 Json 以字符串形式从远程服务器传入时,这并没有多大用处。
因此,如果您可以获取一个 Json 字符串并将其解析为 IDictionary 对象、IList 数组和原始值的嵌套结构,那么您就可以使用 JsonPath 对其进行过滤!幸运的是,我们可以使用具有良好序列化和反序列化功能的 Json.NET 来完成这部分工作。
不幸的是,Json.NET 不会将 Json 字符串反序列化为与 BasicValueSystem 兼容的格式。因此,在 Json.NET 中使用 JsonPath 的首要任务是编写一个实现 IJsonPathValueSystem 并理解 JObject 对象、JArray 数组和 JValue 值的 JsonNetValueSystem JObject.Parse 产生的值。
所以下载 JsonPath 和 Json.NET 并将它们放入 C# 项目中。然后将此类添加到该项目中:
public sealed class JsonNetValueSystem : IJsonPathValueSystem
{
public bool HasMember(object value, string member)
{
if (value is JObject)
return (value as JObject).Properties().Any(property => property.Name == member);
if (value is JArray)
{
int index = ParseInt(member, -1);
return index >= 0 && index < (value as JArray).Count;
}
return false;
}
public object GetMemberValue(object value, string member)
{
if (value is JObject)
{
var memberValue = (value as JObject)[member];
return memberValue;
}
if (value is JArray)
{
int index = ParseInt(member, -1);
return (value as JArray)[index];
}
return null;
}
public IEnumerable GetMembers(object value)
{
var jobject = value as JObject;
return jobject.Properties().Select(property => property.Name);
}
public bool IsObject(object value)
{
return value is JObject;
}
public bool IsArray(object value)
{
return value is JArray;
}
public bool IsPrimitive(object value)
{
if (value == null)
throw new ArgumentNullException("value");
return value is JObject || value is JArray ? false : true;
}
private int ParseInt(string s, int defaultValue)
{
int result;
return int.TryParse(s, out result) ? result : defaultValue;
}
}
现在有了所有三个,我们可以编写一个示例 JsonPath 程序:
class Program
{
static void Main(string[] args)
{
var input = @"
{ ""store"": {
""book"": [
{ ""category"": ""reference"",
""author"": ""Nigel Rees"",
""title"": ""Sayings of the Century"",
""price"": 8.95
},
{ ""category"": ""fiction"",
""author"": ""Evelyn Waugh"",
""title"": ""Sword of Honour"",
""price"": 12.99
},
{ ""category"": ""fiction"",
""author"": ""Herman Melville"",
""title"": ""Moby Dick"",
""isbn"": ""0-553-21311-3"",
""price"": 8.99
},
{ ""category"": ""fiction"",
""author"": ""J. R. R. Tolkien"",
""title"": ""The Lord of the Rings"",
""isbn"": ""0-395-19395-8"",
""price"": 22.99
}
],
""bicycle"": {
""color"": ""red"",
""price"": 19.95
}
}
}
";
var json = JObject.Parse(input);
var context = new JsonPathContext { ValueSystem = new JsonNetValueSystem() };
var values = context.SelectNodes(json, "$.store.book[*].author").Select(node => node.Value);
Console.WriteLine(JsonConvert.SerializeObject(values));
Console.ReadKey();
}
}
产生这个输出:
["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
此示例基于 JsonPath 站点上的 Javascript 示例: