Commits

Toby Inkster committed 37e15b9

integrate JSON::Hyper::process_includes with JSON::Schema removing the need to prepare a schema before use.

  • Participants
  • Parent commits ae9af20

Comments (0)

Files changed (7)

 Bug tracker:  <http://rt.cpan.org/Dist/Display.html?Queue=JSON-Hyper>
 Maintainer:   Toby Inkster <mailto:tobyink@cpan.org>
 
+0.001_01 [2010-08-04]
+ - process_includes is no longer recursive by default.
+
 0.001_00 [2010-08-02]
 
 	:file-release   <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/JSON-Hyper-0.001_00.tar.gz> ;
 	rdfs:comment    "Developer release"@en .
 
+my:v_0-001_01
+
+	a               :Version ;
+	dc:issued       "2010-08-04"^^xsd:date ;
+	:revision       "0.001_01"^^xsd:string ;
+	:file-release   <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/JSON-Hyper-0.001_01.tar.gz> ;
+	dcs:changeset [
+		dcs:versus my:v_0-001_00 ;
+		dcs:item   [ rdfs:label "process_includes is no longer recursive by default."@en ; a dcs:Change ]
+		] .
+
 #############################################################
 
 my:project
 	:tester         toby:i ;
 	:created        "2010-08-01"^^xsd:date ;
 	:license        <http://dev.perl.org/licenses/> , <http://opensource.org/licenses/mit-license.php> ;
-	:release        my:v_0-001_00 .
+	:release        my:v_0-001_00 , my:v_0-001_01 .
 
 #############################################################
 
 <?xml version="1.0" encoding="utf-8"?>
-<rdf:RDF
-   xmlns:dc="http://purl.org/dc/terms/"
-   xmlns:dcs="http://ontologi.es/doap-changeset#"
-   xmlns:foaf="http://xmlns.com/foaf/0.1/"
-   xmlns:my="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
-   xmlns:toby="http://tobyinkster.co.uk/#"
-   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
-   xmlns="http://usefulinc.com/ns/doap#">
-  <rdf:Description rdf:about="file:///home/tai/src/perlmods/JSON-Hyper/Changes.ttl">
-    <dc:creator rdf:resource="http://tobyinkster.co.uk/#i"/>
-    <dc:description xml:lang="en">Revision history for Perl extension JSON::Hyper.</dc:description>
-    <dc:subject rdf:resource="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/project"/>
-    <dc:title>Changes</dc:title>
-  </rdf:Description>
-  <Version rdf:about="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/v_0-001_00">
-    <dc:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-08-02</dc:issued>
-    <file-release rdf:resource="http://backpan.cpan.org/authors/id/T/TO/TOBYINK/JSON-Hyper-0.001_00.tar.gz"/>
-    <revision rdf:datatype="http://www.w3.org/2001/XMLSchema#string">0.001_00</revision>
-    <rdfs:comment xml:lang="en">Developer release</rdfs:comment>
-  </Version>
-  <Project rdf:about="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/project">
-    <bug-database rdf:resource="http://rt.cpan.org/Dist/Display.html?Queue=JSON-Hyper"/>
-    <created rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-08-01</created>
-    <developer rdf:resource="http://tobyinkster.co.uk/#i"/>
-    <documenter rdf:resource="http://tobyinkster.co.uk/#i"/>
-    <download-page rdf:resource="http://search.cpan.org/dist/JSON-Hyper/"/>
-    <homepage rdf:resource="http://search.cpan.org/dist/JSON-Hyper/"/>
-    <license rdf:resource="http://dev.perl.org/licenses/"/>
-    <license rdf:resource="http://opensource.org/licenses/mit-license.php"/>
-    <maintainer rdf:resource="http://tobyinkster.co.uk/#i"/>
-    <name>JSON-Hyper</name>
-    <programming-language>Perl</programming-language>
-    <release rdf:resource="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/v_0-001_00"/>
-    <repository>
-      <SVNRepository>
-        <browse rdf:resource="http://goddamn.co.uk/viewvc/perlmods/JSON-Hyper/"/>
-      </SVNRepository>
-    </repository>
-    <shortdesc xml:lang="en">extract links from JSON via a schema</shortdesc>
-    <tester rdf:resource="http://tobyinkster.co.uk/#i"/>
-  </Project>
-  <foaf:Person rdf:about="http://tobyinkster.co.uk/#i">
-    <ns1:sameAs xmlns:ns1="http://www.w3.org/2002/07/owl#" rdf:resource="http://purl.org/NET/cpan-uri/person/tobyink"/>
-    <foaf:homepage rdf:resource="http://tobyinkster.co.uk/"/>
-    <foaf:mbox rdf:resource="mailto:tobyink@cpan.org"/>
-    <foaf:name>Toby Inkster</foaf:name>
-    <foaf:page rdf:resource="http://search.cpan.org/~tobyink/"/>
-  </foaf:Person>
+<rdf:RDF xmlns:dbug="http://ontologi.es/doap-bugs#" xmlns:dc="http://purl.org/dc/terms/" xmlns:dcs="http://ontologi.es/doap-changeset#" xmlns:doap="http://usefulinc.com/ns/doap#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
+<rdf:Description rdf:nodeID="r6C6225049FF011DFBCB0E829D3C5F46Br0">
+	<dcs:item rdf:nodeID="r6C6225049FF011DFBCB0E829D3C5F46Br1"/>
+	<dcs:versus rdf:resource="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/v_0-001_00"/>
+</rdf:Description>
+<rdf:Description rdf:nodeID="r6C6225049FF011DFBCB0E829D3C5F46Br1">
+	<rdf:type rdf:resource="http://ontologi.es/doap-changeset#Change"/>
+	<rdfs:label xml:lang="en">process_includes is no longer recursive by default.</rdfs:label>
+</rdf:Description>
+<rdf:Description rdf:nodeID="r6C6225049FF011DFBCB0E829D3C5F46Br2">
+	<doap:browse rdf:resource="http://goddamn.co.uk/viewvc/perlmods/JSON-Hyper/"/>
+	<rdf:type rdf:resource="http://usefulinc.com/ns/doap#SVNRepository"/>
+</rdf:Description>
+<rdf:Description rdf:about="file:///home/tai/src/perlmods/JSON-Hyper/Changes.ttl">
+	<dc:creator rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<dc:description xml:lang="en">Revision history for Perl extension JSON::Hyper.</dc:description>
+	<dc:subject rdf:resource="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/project"/>
+	<dc:title>Changes</dc:title>
+</rdf:Description>
+<rdf:Description rdf:about="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/project">
+	<doap:bug-database rdf:resource="http://rt.cpan.org/Dist/Display.html?Queue=JSON-Hyper"/>
+	<doap:created rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-08-01</doap:created>
+	<doap:developer rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<doap:documenter rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<doap:download-page rdf:resource="http://search.cpan.org/dist/JSON-Hyper/"/>
+	<doap:homepage rdf:resource="http://search.cpan.org/dist/JSON-Hyper/"/>
+	<doap:license rdf:resource="http://dev.perl.org/licenses/"/>
+	<doap:license rdf:resource="http://opensource.org/licenses/mit-license.php"/>
+	<doap:maintainer rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<doap:name>JSON-Hyper</doap:name>
+	<doap:programming-language>Perl</doap:programming-language>
+	<doap:release rdf:resource="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/v_0-001_00"/>
+	<doap:release rdf:resource="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/v_0-001_01"/>
+	<doap:repository rdf:nodeID="r6C6225049FF011DFBCB0E829D3C5F46Br2"/>
+	<doap:shortdesc xml:lang="en">extract links from JSON via a schema</doap:shortdesc>
+	<doap:tester rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<rdf:type rdf:resource="http://usefulinc.com/ns/doap#Project"/>
+</rdf:Description>
+<rdf:Description rdf:about="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/v_0-001_00">
+	<dc:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-08-02</dc:issued>
+	<doap:file-release rdf:resource="http://backpan.cpan.org/authors/id/T/TO/TOBYINK/JSON-Hyper-0.001_00.tar.gz"/>
+	<doap:revision rdf:datatype="http://www.w3.org/2001/XMLSchema#string">0.001_00</doap:revision>
+	<rdf:type rdf:resource="http://usefulinc.com/ns/doap#Version"/>
+	<rdfs:comment xml:lang="en">Developer release</rdfs:comment>
+</rdf:Description>
+<rdf:Description rdf:about="http://purl.org/NET/cpan-uri/dist/JSON-Hyper/v_0-001_01">
+	<dcs:changeset rdf:nodeID="r6C6225049FF011DFBCB0E829D3C5F46Br0"/>
+	<dc:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-08-04</dc:issued>
+	<doap:file-release rdf:resource="http://backpan.cpan.org/authors/id/T/TO/TOBYINK/JSON-Hyper-0.001_01.tar.gz"/>
+	<doap:revision rdf:datatype="http://www.w3.org/2001/XMLSchema#string">0.001_01</doap:revision>
+	<rdf:type rdf:resource="http://usefulinc.com/ns/doap#Version"/>
+</rdf:Description>
+<rdf:Description xmlns:ns1="http://www.w3.org/2002/07/owl#" rdf:about="http://tobyinkster.co.uk/#i">
+	<rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Person"/>
+	<ns1:sameAs rdf:resource="http://purl.org/NET/cpan-uri/person/tobyink"/>
+	<foaf:homepage rdf:resource="http://tobyinkster.co.uk/"/>
+	<foaf:mbox rdf:resource="mailto:tobyink@cpan.org"/>
+	<foaf:name>Toby Inkster</foaf:name>
+	<foaf:page rdf:resource="http://search.cpan.org/~tobyink/"/>
+</rdf:Description>
 </rdf:RDF>

File JSON-Hyper-0.001_01.tar.gz

Binary file added.
 configure_requires:
   ExtUtils::MakeMaker: 6.42
 distribution_type: module
-generated_by: 'Module::Install version 0.91'
+generated_by: 'Module::Install version 0.95'
 keywords:
   - JSON
   - schema
   homepage: http://search.cpan.org/dist/JSON-Hyper/
   license: http://dev.perl.org/licenses/
   repository: http://goddamn.co.uk/viewvc/perlmods/JSON-Hyper/
-version: 0.001_00
+version: 0.001_01
          my $hyper    = JSON::Hyper->new($hyperschema);
          my ($result) = $hyper->get('http://example.com/data.json#foo/bar/0');
 
-        Is equivalent to:
+        Is roughly equivalent to:
 
          use JSON;
          use LWP::UserAgent;
          my $object   = from_json($response->decoded_content);
          my $result   = $object->{'foo'}->{'bar'}->[0];
 
+        Note, if called multiple times on the same URL will return not just
+        equivalent objects, but the same object.
+
         So, why does this method return a list of results instead of just a
         single result? In most cases, there will be either 0 or 1 items on
         the list; however, JSONPath allows a path to match multiple nodes,
         so there will occasionally be more than one result.
 
-    "process_includes($object, $base)"
+    "resolve_fragment($object, $fragment)"
+        Used by "get" to resolve the fragment part of a URL against an
+        object.
+
+    "process_includes($object, $base, $recurse)"
         Given an JSON object (or equivalent Perl nested hashref/arrayref
         structure) and optional base URL, crawls the object finding
         rel="full" links, dereferences them using "get" and replaces the
-        appropriate nodes with the retrieved content.
+        appropriate nodes with the retrieved content. $recurse is a boolean.
 
         This has the effect of rel="full" behaving like inclusion does in
         various programming languages.
 
+        This modifies the given object rather than creating a new object.
+
 BUGS
     Please report any bugs to <http://rt.cpan.org/>.
 

File lib/JSON/Hyper.pm

 use URI;
 use URI::Escape qw[uri_unescape];
 
-our $VERSION = '0.001_00';
+our $VERSION = '0.001_01';
+our $DEBUG = 0;
 
 sub json_ref
 {
 
 sub process_includes
 {
-	my ($self, $original, $base) = @_;
+	my ($self, $original, $base, $recurse) = @_;
 	$original = from_json($original) unless ref $original;
-	my $object = dclone($original);
-	$self->_process_includes($object);
-	return $object;
+	$self->_process_includes($original, $base, $recurse);
+	return $original;
 }
 
 sub _process_includes
 {
-	my ($self, $object, $base) = @_;
+	my ($self, $object, $base, $recurse) = @_;
 	
 	my @links = $self->find_links($object, $base);
 	my $full;
 			delete $object->{ $full->{'property'} };
 			while (my($k,$v) = each %$substitute)
 			{
-				$object->{$k} = dclone($v);
+				$object->{$k} = $v;
 			}
 		}
+		return;
 	}
-	elsif (ref $object eq 'ARRAY')
+	return unless $recurse;
+
+	if (ref $object eq 'ARRAY')
 	{
 		foreach my $i (@$object)
 		{
-			$self->_process_includes($i, $base);
+			$self->_process_includes($i, $base, $recurse);
 		}
 	}
 	elsif (ref $object eq 'HASH')
 	{
 		foreach my $i (values %$object)
 		{
-			$self->_process_includes($i, $base);
+			$self->_process_includes($i, $base, $recurse);
 		}
 	}
 }
 {
 	my ($self, $uri) = @_;
 	my ($resource, $fragment) = split /\#/, $uri, 2;
-	
-	my $response = $self->ua->get($resource);
-	return unless $response->is_success;
-	
-	my $object = from_json( $response->decoded_content );
+	my $object = $self->_get($resource);
 	return $object unless $fragment;
 	return $self->resolve_fragment($object, $fragment);
 }
 
+sub _get
+{
+	my ($self, $resource) = @_;
+	
+	warn "GETting $resource" if $DEBUG;
+	
+	unless ($self->{'cache'}->{$resource})
+	{
+		my $response = $self->ua->get($resource);
+		return unless $response->is_success;
+		$self->{'cache'}->{$resource} = from_json( $response->decoded_content );
+		$self->{'http_cache'}->{$resource} = $resource;
+	}
+	
+	my @r = ($self->{'cache'}->{$resource}, $self->{'http_cache'}->{$resource});
+	return wantarray ? @r : $r[0];
+}
+
 sub resolve_fragment
 {
 	my ($self, $object, $fragment) = @_;
 	my $style = $self->schema->{fragmentResolution} || 'slash-delimited';
-	
+
 	$object = from_json($object) unless ref $object;
 	return $object unless $fragment;
-	
+
+	$fragment =~ s!^#!!;
+
 	if ($style =~ /^(json.?)?path$/i)
 	{
 		my $jsonp   = JSON::Path->new(uri_unescape($fragment));
 		my @matches = $jsonp->values($object);
 		return @matches;
 	}
+	elsif (lc $style eq 'dot-delimited')
+	{
+		$fragment =~ s!^\.!!;
+	}
+	elsif (lc $style eq 'slash-delimited')
+	{
+		$fragment =~ s!^/!!;
+	}
+	else
+	{
+		carp "Unknown fragment resolution method: $style";
+		return;
+	}
+	
+	return $self->_resolve_fragment($object, $fragment);
+}
+
+sub _resolve_fragment
+{
+	my ($self, $object, $fragment) = @_;
+	my $style = $self->schema->{fragmentResolution} || 'slash-delimited';
 	
 	my ($first, $rest);
 	if (lc $style eq 'dot-delimited')
 	{
 		($first, $rest) = split /\//, $fragment, 2;
 	}
-	else
-	{
-		carp "Unknown fragment resolution method: $style";
-		return;
-	}
 
 	$first = uri_unescape($first);
 
 	
 	if (length $rest)
 	{
-		return $self->resolve_fragment($value, $rest);
+		return $self->_resolve_fragment($value, $rest);
 	}
 	else
 	{
  my $hyper    = JSON::Hyper->new($hyperschema);
  my ($result) = $hyper->get('http://example.com/data.json#foo/bar/0');
 
-Is equivalent to:
+Is roughly equivalent to:
 
  use JSON;
  use LWP::UserAgent;
  my $object   = from_json($response->decoded_content);
  my $result   = $object->{'foo'}->{'bar'}->[0];
 
+Note, if called multiple times on the same URL will return not just
+equivalent objects, but the same object.
+
 So, why does this method return a list of results instead of just
 a single result? In most cases, there will be either 0 or 1 items
 on the list; however, JSONPath allows a path to match multiple
 nodes, so there will occasionally be more than one result.
 
-=item C<< process_includes($object, $base) >>
+=item C<< resolve_fragment($object, $fragment) >>
+
+Used by C<get> to resolve the fragment part of a URL against an object.
+
+=item C<< process_includes($object, $base, $recurse) >>
 
 Given an JSON object (or equivalent Perl nested hashref/arrayref
 structure) and optional base URL, crawls the object finding
 rel="full" links, dereferences them using C<get> and replaces
-the appropriate nodes with the retrieved content.
+the appropriate nodes with the retrieved content. $recurse
+is a boolean.
 
 This has the effect of rel="full" behaving like inclusion does
 in various programming languages.
 
+This modifies the given object rather than creating a new object.
+
 =back
 
 =head1 BUGS