Запуск предиката выражения в Newtonsoft.Json.Linq.JObject

Я создаю список JObject, как показано ниже. Я хотел бы найти коллекцию, используя выражение запроса. В приведенном ниже примере кода я использую запрос Jsonpath, чтобы найти все объекты позиции типа Buy (enum Buy имеет значение int 1)

List<JObject> list = new List<JObject>();
list.Add(JObject.FromObject(new Position() { PositionType = PositionType.Buy, Investment = new Investment() { InvestmentCode = "AAPL" } }));
list.Add(JObject.FromObject(new Position() { PositionType = PositionType.Sell, Investment = new Investment() { InvestmentCode = "AAPL" } }));

var x = list.Find(j =>
{
    JToken token =  j.SelectToken("$[?(@.PositionType == 1)]");
    return token != null;
});

Метод SelectToken возвращает нулевое значение в предикате. Я не уверен, что использую правильный метод. Есть ли способ оценки предиката на объекте?

1 ответ

Это не очень хорошо объясняется SelectTokens() документация или стандарт JSONPath, но [?(script)] оператор может быть определен для условного выбора дочерних объектов. Это потому что [?()] оператор на самом деле является комбинацией оператора сценария, вложенного в оператор дочерний / нижний индекс. Из стандарта:

Вот полный обзор и сравнение элементов синтаксиса JSONPath с его аналогами XPath.

XPath    JSONPath    Description 
/        . or []     child operator 
[]       []          subscript operator. XPath uses it to iterate over element collections and for predicates. In Javascript and JSON it is the native array operator. 
[]       ?()         applies a filter (script) expression. 
n/a      ()          script expression, using the underlying script engine. 

Единственными примерами стандартных шоу из [?()] оператор находится в сопоставлении свойств объектов внутри массивов и возвращает эти объекты.

Таким образом, если я сделаю SelectTokens() на [{"PositionType": 1}] с помощью "$[?(@.PositionType == 1)]" тогда один объект возвращается, но делает это на {"PositionType": 1} (как вы пытаетесь сделать внутри вашего Find() предикат) ничего не возвращает.

Json.NET не совсем уникален в своей интерпретации стандарта. Вот результаты попыток совпадения {"PositionType": 1} против "$[?(@.PositionType == 1)]" а также $..[?(@.PositionType == 1)] используя различные парсеры JSONPath:

  • http://www.jsonquerytool.com/ - ни один не соответствует.
  • http://jsonpath.com/ - ни один не соответствует.
  • http://jsonpath.herokuapp.com/
    • "Jayway": - оба совпадают.
    • "Гатлинг" - "$[?(@.PositionType == 1)]" Матчи, $..[?(@.PositionType == 1)] ошибки. (Обновление: с версией Gatling 0.6.7, оба совпадают.)
    • "Небхале" - обе ошибки.
    • "Гесснер" - ни один не совпадает.

Вы можете сообщить о проблеме, связанной с поведением Json.NET, но, учитывая несоответствие между реализациями, она может быть не решена. Стандарт JSONPath может быть недостаточно четким и недостаточно стабильным для ваших нужд по сравнению с XPath на данный момент.

См. Также Newtonsoft JSON SelectToken для получения данных из нескольких частей документа JSON? и Как выбрать JToken на основе нескольких имен кандидатов в JSONPath?,

Другие вопросы по тегам