Skip to content

Commit

Permalink
Updated docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
phptek committed Jun 21, 2016
1 parent 627b5c6 commit 301d750
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 22 deletions.
29 changes: 26 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ JSON storage and querying.

## Introduction

The module exposes a simple query API based on the [JSON operators found in Postgres v9.2+](https://www.postgresql.org/docs/9.5/static/functions-json.html),
The module exposes a fully featured JSON query API that allows developers to use either XPath-like queries using [JSONPath](http://goessner.net/articles/JsonPath/)
or a JSON-aware RDBMS-like syntax such as those found in the [JSON operators of Postgres v9.2+](https://www.postgresql.org/docs/9.5/static/functions-json.html),
but with some modifications:

In Postgres both the `->` and `->>` operators act as string and integer key matchers on a JSON array or object respectively. The module
Expand All @@ -25,9 +26,26 @@ In Postgress the `#>` path match operator can act as an object or a text matcher
the `#>` operator is *just a simple path matcher*.

I see nothing but confusion arising if the same operator were to be treated differently
depending on the specific *type of JSON* stored.
depending on the specific *type of JSON* stored. I'm a reasonable man however, and am prepared for a discussion :-)

I'm a reasonable man however, and am prepared for a discussion on it, if any were to be forthcoming.
Regardless of the type of query in-use you can set what form you'd like the data returned in via the `setReturnType()` method, on a query by query basis.

Legitimate types are:

* JSON
* Array
* SilverStripe

If using `SilverStripe`, the module will automatically cast the result(s) to one of SilverStripe's four native "scalar" `DBObject` subtypes:

* `Boolean`
* `Int`
* `Float`
* `Varchar`

If there are multiple results, the output will be an indexed array containing a single-value array for each result found.

See [the usage docs](docs/en/usage.md) for examples of JSONPath and Postgres queries.

Note: This module's query API is based on a relatively simple JSON to array conversion principle.
It does *not* use Postgres' or MySQL's JSON operators at the ORM level. The aim however
Expand Down Expand Up @@ -65,6 +83,11 @@ See: [CONTRIBUTING.md](CONTRIBUTING.md).

Please include all details, no matter how small. If it were *your module*, what would you need to know from a bug/feature request? :-)

## Credits

* [Axel Anceau](https://github.com/Peekmo/) for his packaging-up of the pretty amazing JSONPath implementation by [Stefan Goessner](https://code.google.com/archive/p/jsonpath/)
* [Stefan Goessner](https://code.google.com/archive/p/jsonpath/) for the original work on JSONPath dating back to 2005!

## TODO

* Lose the fugly way that data is queried via `$this->dbObject()`
Expand Down
19 changes: 2 additions & 17 deletions code/models/fieldtypes/JSONText.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* Simple text-based database field for storing and querying JSON structured data.
*
* JSON sub-structures can be queried in a variety of ways using special operators who's syntax closely mimics those used
* JSON sub-structures can be queried in a variety of ways using special operators who's syntax closely mimics those used
* in native JSON queries in PostGreSQL v9.2+.
*
* Note: The extraction techniques employed here are simple key / value comparisons. They do not use any native JSON
Expand Down Expand Up @@ -357,24 +357,9 @@ public function query($operator, $operand)
return $this->returnAsType([]);
}

/**
* Alias of self::query().
*
* @param string $operator
* @return mixed string|array
* @throws \JSONText\Exceptions\JSONTextException
*/
public function extract($operator)
{
return $this->query($operator);
}

/**
* Based on the passed operator, ensure the correct backend matcher method is called.
*
* @param mixed $key
* @param mixed $val
* @param int $idx
*
* @param array $args
* @return array
* @throws \JSONText\Exceptions\JSONTextException
Expand Down
91 changes: 89 additions & 2 deletions docs/en/usage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Usage

In the examples below, if you pass invalid queries or malformed JSON (where applicable) an instance of `JSONTextException` is thrown.

## General

You can stipulate what format you want your query results back as via passing one of **json** or **array** to `setReturnType()`, thus:

// JSON
Expand All @@ -11,8 +15,12 @@ You can stipulate what format you want your query results back as via passing on
$field = JSONText\Fields\JSONText::create('MyJSON');
$field->setValue('{"a": {"b":{"c": "foo"}}}');
$field->setReturnType('array');

In the examples below, if you pass invalid queries or malformed JSON (where applicable) an instnce of `JSONTextException` is thrown.

// SilverStripe
// Will give you Varchar instances for each scalar value
$field = JSONText\Fields\JSONText::create('MyJSON');
$field->setValue('{"a": {"b":{"c": "foo"}}}');
$field->setReturnType('silverstripe');

class MyDataObject extends DataObject
{
Expand Down Expand Up @@ -45,7 +53,16 @@ In the examples below, if you pass invalid queries or malformed JSON (where appl
{
return $this->dbObject('MyJSON')->nth($n);
}
}

## Postgres Operators
class MyOtherDataObject extends DataObject
{
private static $db = [
'MyJSON' => 'JSONText'
];

/**
* Returns a key=>value pair based on a strict integer -> key match.
* If a string is passed, an empty array is returned.
Expand Down Expand Up @@ -74,3 +91,73 @@ In the examples below, if you pass invalid queries or malformed JSON (where appl
}
}

## JSONPath Expressions

Not implemented yet, but syntax will be very similar to the following example:

class MyDataObject extends DataObject
{
/*
* @var string
*/
protected $stubJSON = '{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
},
{ "category": "fiction",
"author": "Evelyn Waugh",
}
]
}';

private static $db = [
'MyJSON' => 'JSONText'
];
public function requireDefaultRecords()
{
parent::requireDefaultRecords();
if (!$this->MyJSON) {
$this->setValue($this->stubJSON);
}
}
public function doStuffWithMyJSON()
{
// Query as Array
$expr = '$.store.book[*].author'; // The authors of all books in the store
$result = $this->dbObject('MyJSON')->query($expr);
$result->setReturnType('array');
var_dump($result); // Returns ['Nigel Rees', 'Evelyn Waugh']
// Query as Array
$expr = '$..book[1]'; // The second book
$result = $this->dbObject('MyJSON')->query($expr);
$result->setReturnType('array');
var_dump($this->dbObject('MyJSON')->query($expr)); // Returns ['book' => ['category' => 'reference'], ['author' => 'Nigel Rees']]
// Query as JSON
$expr = '$..book[1]'; // The second book
$result = $this->dbObject('MyJSON')->query($expr);
$result->setReturnType('json');
var_dump($this->dbObject('MyJSON')->query($expr));
/* Returns:
{"book": [
{
"category": "reference",
"author": "Nigel Rees",
},
{
"category": "fiction",
"author": "Evelyn Waugh"
} ] }
*/
}
}


0 comments on commit 301d750

Please sign in to comment.