Проблема, с которой вы столкнулись, заключается в том, что версия JsonPath на C # не включает в себя анализатор Json, поэтому вы должны использовать его с другой средой Json, которая обрабатывает сериализацию и десериализацию.
Способ работы JsonPath - использовать интерфейс с именем IJsonPathValueSystem
для прохождения проанализированных объектов Json. JsonPath поставляется со встроенным BasicValueSystem
, который использует интерфейс IDictionary
для представления объектов Json и интерфейс IList
для представления массивов Json.
Вы можете создавать свои собственные BasicValueSystem
-совместимые объекты Json, создавая их с помощью инициализаторов коллекции C #, но это не очень полезно, когда ваш Json приходит в виде строк с удаленного сервера, например.
Так что, если бы только вы могли взять строку Json и разобрать ее во вложенную структуру из IDictionary
объектов, IList
массивов и примитивных значений, вы могли бы затем использовать JsonPath для ее фильтрации! К счастью, мы можем использовать Json.NET, которая обладает хорошими возможностями сериализации и десериализации для выполнения этой части работы.
К сожалению, Json.NET не десериализует строки Json в формат, совместимый с BasicValueSystem
. Поэтому первая задача для использования JsonPath с Json.NET - написать JsonNetValueSystem
, который реализует IJsonPathValueSystem
и который понимает JObject
объекты, JArray
массивы и JValue
значения, которые 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"]
Этот пример основан на образце Javascript на сайте JsonPath: