Skip to content

Commit

Permalink
Introduce JsonLdSerializable interface and make everything serializable
Browse files Browse the repository at this point in the history
This addresses #15.
  • Loading branch information
lanthaler committed Feb 4, 2013
1 parent cbf42fd commit a38c723
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 19 deletions.
28 changes: 27 additions & 1 deletion Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace ML\JsonLD;

use stdClass as Object;
use ML\IRI\IRI;

/**
Expand All @@ -18,7 +19,7 @@
*
* @author Markus Lanthaler <[email protected]>
*/
class Document implements DocumentInterface
class Document implements DocumentInterface, JsonLdSerializable
{
/**
* @var IRI The document's IRI
Expand Down Expand Up @@ -171,4 +172,29 @@ public function removeGraph($graph = null)
unset($this->namedGraphs[$name]);
}
}

/**
* {@inheritdoc}
*/
public function toJsonLd($useNativeTypes = true)
{
$defGraph = $this->defaultGraph->toJsonLd($useNativeTypes);

if (0 === count($this->namedGraphs)) {
return $defGraph;
}

foreach ($this->namedGraphs as $graphName => $graph) {
$namedGraph = new Object();
$namedGraph->{'@id'} = $graphName;
$namedGraph->{'@graph'} = $graph->toJsonLd($useNativeTypes);

$defGraph[] = $namedGraph;
}

$document = new Object();
$document->{'@graph'} = $defGraph;

return array($document);
}
}
19 changes: 18 additions & 1 deletion Graph.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @author Markus Lanthaler <[email protected]>
*/
class Graph implements GraphInterface
class Graph implements GraphInterface, JsonLdSerializable
{
/**
* @var DocumentInterface The document this graph belongs to.
Expand Down Expand Up @@ -219,6 +219,23 @@ public function merge(GraphInterface $graph)
return $this;
}

/**
* {@inheritdoc}
*/
public function toJsonLd($useNativeTypes = true)
{
// Bring nodes into a deterministic order
$nodes = $this->nodes;
ksort($nodes);
$nodes = array_values($nodes);

$serializeNode = function ($node) use ($useNativeTypes) {
return $node->toJsonLd($useNativeTypes);
};

return array_map($serializeNode, $nodes);
}

/**
* Create a new blank node identifier unique to the document.
*
Expand Down
53 changes: 52 additions & 1 deletion Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

namespace ML\JsonLD;

use stdClass as Object;

/**
* A Node represents a node in a JSON-LD graph.
*
* @author Markus Lanthaler <[email protected]>
*/
class Node implements NodeInterface
class Node implements NodeInterface, JsonLdSerializable
{
/** The @type constant. */
const TYPE = '@type';
Expand Down Expand Up @@ -356,6 +358,55 @@ public function equals(NodeInterface $other)
return $this === $other;
}

/**
* {@inheritdoc}
*/
public function toJsonLd($useNativeTypes = true)
{
$node = new \stdClass();

// Only label blank nodes if other nodes point to it
if ((false === $this->isBlankNode()) || (count($this->getReverseProperties()) > 0)) {
$node->{'@id'} = $this->getId();
}

$properties = $this->getProperties();

foreach ($properties as $prop => $values) {
if (false === is_array($values)) {
$values = array($values);
}

if (self::TYPE === $prop) {
$node->{'@type'} = array();
foreach ($values as $val) {
$node->{'@type'}[] = $val->getId();
}

continue;
}

$node->{$prop} = array();

foreach ($values as $value) {
if ($value instanceof NodeInterface) {
$ref = new \stdClass();
$ref->{'@id'} = $value->getId();
$node->{$prop}[] = $ref;
} elseif (is_object($value)) { // language-tagged string or typed value
$node->{$prop}[] = $value->toJsonLd($useNativeTypes);
} else {
$val = new Object();
$val->{'@value'} = $value;
$node->{$prop}[] = $val;
}
}

}

return $node;
}

/**
* Add a reverse property.
*
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ $doc = JsonLD::getDocument('document.jsonld');
// get the default graph
$graph = $doc->getGraph();

// get all nodes in the document
// get all nodes in the graph
$nodes = $graph->getNodes();

// retrieve a node by ID
Expand All @@ -99,14 +99,17 @@ $node = $graph->getNode('http://example.com/node1');
// get a property
$node->getProperty('http://example.com/vocab/name');

// add a new blank node to the document
// add a new blank node to the graph
$newNode = $graph->createNode();

// link the new blank node to the existing node
$node->addPropertyValue('http://example.com/vocab/link', $newNode);

// even reverse properties are supported; this returns $newNode
$node->getReverseProperty('http://example.com/vocab/link');

// serialize the graph and convert it to a string
$serialized = JsonLD::toString($graph->toJsonLd());
```


Expand Down
130 changes: 129 additions & 1 deletion Test/GraphTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,8 @@ public function testMerge()

$this->assertEquals(
array('2', 'and a different name in graph 2'),
$node2->getProperty('http://vocab.com/name'), 'n2->name'
$node2->getProperty('http://vocab.com/name'),
'n2->name'
);

$this->assertSame(array($node3, $node4), $node2->getProperty('http://vocab.com/link'), 'n2 -link-> n3 & n4');
Expand Down Expand Up @@ -756,4 +757,131 @@ public function testMerge()
$this->assertSame($graph2, $n->getGraph(), 'linked to graph (graph 2)');
}
}

/**
* Tests the serialization of nodes
*/
public function testSerializeNode()
{
$expected = JsonLD::parse(
'{
"@id": "http://example.com/node/1",
"@type": [ "http://vocab.com/type/node" ],
"http://vocab.com/name": [ { "@value": "1" } ],
"http://vocab.com/link": [ { "@id": "http://example.com/node/2" } ],
"http://vocab.com/contains": [ { "@id": "_:b0" } ]
}'
);

$node1 = $this->graph->getNode('http://example.com/node/1');
$this->assertEquals($expected, $node1->toJsonLd(), 'Serialize node 1');
}

/**
* Tests the serialization of graphs
*/
public function testSerializeGraph()
{
// This is the expanded and flattened version of the test document
// (the blank node labels have been renamed from _:t... to _:b...)
$expected = JsonLD::parse(
'[{
"@id": "_:b0",
"http://vocab.com/nested": [{
"@value": "1.1"
}]
}, {
"@id": "_:b1",
"http://vocab.com/nested": [{
"@value": "2.1"
}]
}, {
"@id": "_:b2",
"http://vocab.com/nested": [{
"@value": "2.2"
}]
}, {
"@id": "_:b3",
"http://vocab.com/nested": [{
"@value": "3.1"
}]
}, {
"@id": "http://example.com/node/1",
"@type": ["http://vocab.com/type/node"],
"http://vocab.com/contains": [{
"@id": "_:b0"
}],
"http://vocab.com/link": [{
"@id": "http://example.com/node/2"
}],
"http://vocab.com/name": [{
"@value": "1"
}]
}, {
"@id": "http://example.com/node/2",
"@type": ["http://vocab.com/type/nodeWithAliases"],
"http://vocab.com/aliases": [{
"@value": "node2"
}, {
"@value": 2
}],
"http://vocab.com/contains": [{
"@id": "_:b1"
}, {
"@id": "_:b2"
}],
"http://vocab.com/lang": [{
"@language": "en",
"@value": "language-tagged string"
}],
"http://vocab.com/link": [{
"@id": "http://example.com/node/3"
}],
"http://vocab.com/name": [{
"@value": "2"
}],
"http://vocab.com/typed": [{
"@type": "http://vocab.com/type/datatype",
"@value": "typed value"
}]
}, {
"@id": "http://example.com/node/3",
"@type": ["http://vocab.com/type/node"],
"http://vocab.com/contains": [{
"@id": "_:b3"
}],
"http://vocab.com/lang": [{
"@language": "en",
"@value": "language-tagged string: en"
}, {
"@language": "de",
"@value": "language-tagged string: de"
}],
"http://vocab.com/link": [{
"@id": "http://example.com/node/1"
}],
"http://vocab.com/name": [{
"@value": "3"
}],
"http://vocab.com/typed": [{
"@type": "http://vocab.com/type/datatype",
"@value": "typed value"
}, {
"@language": "ex:/type/otherDataType",
"@value": "typed value"
}, {
"@language": "ex:/type/datatype",
"@value": "typed value"
}]
}, {
"@id": "http://vocab.com/type/datatype"
}, {
"@id": "http://vocab.com/type/node"
}, {
"@id": "http://vocab.com/type/nodeWithAliases"
}]'
);

$this->assertEquals($expected, $this->graph->toJsonLd(false), 'Serialize graph');
}
}
14 changes: 1 addition & 13 deletions Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
* @author Markus Lanthaler <[email protected]>
*/
abstract class Value
abstract class Value implements JsonLdSerializable
{
/**
* The value in the form of a string
Expand Down Expand Up @@ -99,18 +99,6 @@ public static function fromJsonLd(Object $element)
return new TypedValue($value, (null === $type) ? RdfConstants::XSD_STRING : $type);
}

/**
* Convert this instance to a JSON-LD element in expanded form
*
* @param boolean $useNativeTypes If set to true, native types are used
* for xsd:integer, xsd:double, and
* xsd:boolean, otherwise typed strings
* will be used instead.
*
* @return string|integer|float|boolean|Object The JSON-LD element.
*/
abstract public function toJsonLd($useNativeTypes = true);

/**
* Compares this instance to the specified value.
*
Expand Down

0 comments on commit a38c723

Please sign in to comment.