Существует ли язык запросов для JSON?

После тщательного прочтения документации я пришел к выводу, что невозможно выйти за пределы сцены. Тем не менее, можно вручную установить пределы сцены на нечто большее, чем фактическая сцена. Самое простое решение состоит в том, чтобы установить достаточно большую сцену в начале, как предложено здесь . Однако это не динамично и имеет ограничения. Я решил эту проблему путем автоматического вычисления пределов сцены при каждом обновлении сцены. Для этого я подключаю QGraphicsScene::changed к слоту, в котором вычисляется автоматический размер сцены, и вручную заставляю сцену обновляться движением мыши. Последний класс с желаемым поведением:

Заголовок

#ifndef CUSTOMGRAPHICSVIEW_H
#define CUSTOMGRAPHICSVIEW_H

#include 

class CustomGraphicsView : public QGraphicsView
{
  Q_OBJECT
public:
  CustomGraphicsView(QWidget* parent = nullptr);

protected:
  virtual void wheelEvent(QWheelEvent* event) override;
  virtual void mouseMoveEvent(QMouseEvent* event) override;
  virtual void mousePressEvent(QMouseEvent* event) override;
  virtual void mouseReleaseEvent(QMouseEvent* event) override;

  void autocomputeSceneSize(const QList& region);
};

#endif  // CUSTOMGRAPHICSVIEW_H

CPP

#include "customview.h"

#include 

CustomGraphicsView::CustomGraphicsView(QWidget* parent) : QGraphicsView(parent)
{
  // Set up new scene
  setScene(new QGraphicsScene);

  // Do not show scroll bars
  setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

  // Connect scene update to autoresize
  connect(scene(), &QGraphicsScene::changed, this, &CustomGraphicsView::autocomputeSceneSize);
}

void CustomGraphicsView::wheelEvent(QWheelEvent* event)
{
  // if ctrl pressed, use original functionality
  if (event->modifiers() & Qt::ControlModifier)
    QGraphicsView::wheelEvent(event);
  // Rotate scene
  else if (event->modifiers() & Qt::ShiftModifier)
  {
    if (event->delta() > 0)
    {
      rotate(1);
    }
    else
    {
      rotate(-1);
    }
  }
  // Zoom
  else
  {
    ViewportAnchor previous_anchor = transformationAnchor();
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    if (event->delta() > 0)
    {
      scale(1.1, 1.1);
    }
    else
    {
      scale(0.9, 0.9);
    }
    setTransformationAnchor(previous_anchor);
  }
}

void CustomGraphicsView::mouseMoveEvent(QMouseEvent* event)
{
  QGraphicsView::mouseMoveEvent(event);
  if (event->buttons() & Qt::LeftButton)
    // If we are moveing with the left button down, update the scene to trigger autocompute
    scene()->update(mapToScene(rect()).boundingRect());
}

void CustomGraphicsView::mousePressEvent(QMouseEvent* event)
{
  if (event->buttons() & Qt::LeftButton)
    // Set drag mode when left button is pressed
    setDragMode(QGraphicsView::ScrollHandDrag);
  QGraphicsView::mousePressEvent(event);
}

void CustomGraphicsView::mouseReleaseEvent(QMouseEvent* event)
{
  if (dragMode() & QGraphicsView::ScrollHandDrag)
    // Unset drag mode when left button is released
    setDragMode(QGraphicsView::NoDrag);
  QGraphicsView::mouseReleaseEvent(event);
}

void CustomGraphicsView::autocomputeSceneSize(const QList& region)
{
  Q_UNUSED(region);

  // Widget viewport recangle
  QRectF widget_rect_in_scene(mapToScene(-20, -20), mapToScene(rect().bottomRight() + QPoint(20, 20)));

  // Copy the new size from the old one
  QPointF new_top_left(sceneRect().topLeft());
  QPointF new_bottom_right(sceneRect().bottomRight());

  // Check that the scene has a bigger limit in the top side
  if (sceneRect().top() > widget_rect_in_scene.top())
    new_top_left.setY(widget_rect_in_scene.top());

  // Check that the scene has a bigger limit in the bottom side
  if (sceneRect().bottom() < widget_rect_in_scene.bottom())
    new_bottom_right.setY(widget_rect_in_scene.bottom());

  // Check that the scene has a bigger limit in the left side
  if (sceneRect().left() > widget_rect_in_scene.left())
    new_top_left.setX(widget_rect_in_scene.left());

  // Check that the scene has a bigger limit in the right side
  if (sceneRect().right() < widget_rect_in_scene.right())
    new_bottom_right.setX(widget_rect_in_scene.right());

  // Set new scene size
  setSceneRect(QRectF(new_top_left, new_bottom_right));
}

213
задан serv-inc 16 September 2015 в 02:23
поделиться

5 ответов

Sure, how about:

They all seem to be a bit work in progress, but work to some degree. They are also similar to XPath and XQuery conceptually; even though XML and JSON have different conceptual models (hierarchic vs object/struct).

EDIT Sep-2015: Actually there is now JSON Pointer standard that allows very simple and efficient traversal of JSON content. It is not only formally specified, but also supported by many JSON libraries. So I would call it actual real useful standard, although due to its limited expressiveness it may or may not be considered Query Language per se.

86
ответ дан 23 November 2019 в 04:29
поделиться

Текущая реализация Jaql нацелена на обработку больших данных с использованием кластера Hadoop, поэтому это может быть больше, чем нужно. Тем не менее, он легко запускается без кластера Hadoop (но все же для его компиляции требуется код Hadoop и его зависимости, которые в основном включены). Небольшая реализация Jaql, которая может быть встроена в Javascript и в браузер, станет отличным дополнением к проекту.

Ваши примеры выше легко написаны на jaql:

$data = [{"x": 2, "y": 0}, {"x": 3, "y": 1}, {"x": 4, "y": 1}];

$data -> filter $.y > 0 -> transform $.x -> sum(); // 7

$data -> filter $.y > 0 -> transform $.x; // [3,4]

Конечно, есть и многое другое. Например:

// Compute multiple aggregates and change nesting structure:
$data -> group by $y = $.y into { $y, s:sum($[*].x), n:count($), xs:$[*].x}; 
    // [{ "y": 0, "s": 2, "n": 1, "xs": [2]   },
    //  { "y": 1, "s": 7, "n": 2, "xs": [3,4] }]

// Join multiple data sets:
$more = [{ "y": 0, "z": 5 }, { "y": 1, "z": 6 }];
join $data, $more where $data.y == $more.y into {$data, $more};
    // [{ "data": { "x": 2, "y": 0 }, "more": { "y": 0, "z": 5 }},
    //  { "data": { "x": 3, "y": 1 }, "more": { "y": 1, "z": 6 }},
    //  { "data": { "x": 4, "y": 1 }, "more": { "y": 1, "z": 6 }}]

Jaql можно скачать / обсудить по адресу http://code.google.com/p/jaql/

1
ответ дан 23 November 2019 в 04:29
поделиться

Я остановлюсь на идее простого использования вашего собственного javascript, но для чего-то более сложного вы можете взглянуть на данные dojo . Не использовал его, но, похоже, он дает вам примерно тот интерфейс запросов, который вы ищете.

1
ответ дан 23 November 2019 в 04:29
поделиться

Если вы используете .NET, то Json.NET поддерживает запросы LINQ поверх JSON. Эта запись имеет несколько примеров. Он поддерживает фильтрацию, отображение, группировку и т. Д.

6
ответ дан 23 November 2019 в 04:29
поделиться

I ' Рекомендую мой проект, над которым я работаю, под названием jLinq . Я жду отзывов, поэтому мне было бы интересно услышать, что вы думаете.

Если позволяет вам писать запросы, аналогичные тем, которые вы делаете в LINQ ...

var results = jLinq.from(records.users)

    //you can join records
    .join(records.locations, "location", "locationId", "id")

    //write queries on the data
    .startsWith("firstname", "j")
    .or("k") //automatically remembers field and command names

    //even query joined items
    .equals("location.state", "TX")

    //and even do custom selections
    .select(function(rec) {
        return {
            fullname : rec.firstname + " " + rec.lastname,
            city : rec.location.city,
            ageInTenYears : (rec.age + 10)
        };
    });

Это также полностью расширяемо!

Документация все еще в процессе,

48
ответ дан 23 November 2019 в 04:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: