Commits

Toby Inkster committed 253a21e

Better way of implementing ->nodePath.

  • Participants
  • Parent commits 7147a09

Comments (0)

Files changed (4)

 my $obj = from_json('{"foo":1,"bar":[{"quux":2},3,4]}');
 $obj->{baz} = [7,8,9];
 push @{ $obj->{baz} }, {'xyzzy'=>5};
+unshift @{ $obj->{baz} }, {'xyzzy'=>1};
 say ref $obj;
 say blessed($obj); 
 say to_json($obj,{'canonical'=>1});
 say $obj->{'bar'}->can('count');
+say $obj->{'baz'}[4]->nodePath;
 say join ',', sort $obj->{'bar'}->parentNode->keys;
 print Dumper($obj);

File lib/JSON/JOM.pm

 	if (CORE::ref($object) eq 'ARRAY'
 	or  CORE::ref($object) eq 'JSON::JOM::Array')
 	{
-		$rv = JSON::JOM::Array->new([@$object],{nodePath=>'$',rootNode=>$object});
+		$rv = JSON::JOM::Array->new([@$object],{rootNode=>1});
 	}
 	elsif (CORE::ref($object) eq 'HASH'
 	or     CORE::ref($object) eq 'JSON::JOM::Object')
 	{
-		$rv = JSON::JOM::Object->new({%$object},{nodePath=>'$',rootNode=>$object});
+		$rv = JSON::JOM::Object->new({%$object},{rootNode=>1});
 	}
 	
 	return $rv if defined $rv;

File lib/JSON/JOM/Array.pm

 	my $self = bless \@self, $class;
 	$JSON::JOM::Object::TIEMAP->{ Scalar::Util::refaddr(tied(@self)) } = $self;
 	
+	$meta ||= {};
+	while (my ($k,$v) = each %$meta)
+	{
+		$self->meta->{$k} = $v;
+	}
+	
+	if ($self->meta->{rootNode} == 1)
+	{
+		$self->meta->{rootNode} = $self;
+	}
+	
 	for(my $i=0; $i < scalar @$data; $i++)
 	{
 		$self[$i] = $data->[$i];
 	}
 	
-	$meta ||= {};
-	while (my ($k,$v) = each %$meta)
-	{
-		$meta->{$k} = $v;
-	}
-	
 	return $self;
 }
 
 	}
 }
 
+sub UNSHIFT
+{
+	my $this = shift;
+	foreach (@_)
+	{
+		unshift @$this, JSON::JOM::Object::Tie::sanitise($this, 0, $_);
+	}
+	for (my $i=0; $i < scalar @$this; $i++)
+	{
+		if (Scalar::Util::blessed($this->[$i]) && $this->[$i]->can('nodeIndex'))
+		{
+			$this->[$i]->nodeIndex($i);
+		}
+	}
+}
+
 1;
 

File lib/JSON/JOM/Object.pm

 use 5.008;
 use common::sense;
 
+use Carp;
 use Module::Pluggable search_path => qw[JSON::JOM::Plugins], require => 1, sub_name => '_plugins';
 use Scalar::Util qw[];
 
 	my $self = bless \%self, $class;
 	$TIEMAP->{ Scalar::Util::refaddr(tied(%self)) } = $self;
 	
+	$meta ||= {};
+	while (my ($k,$v) = each %$meta)
+	{
+		$self->meta->{$k} = $v;
+	}
+	
+	if ($self->meta->{rootNode} == 1)
+	{
+		$self->meta->{rootNode} = $self;
+	}
+	
 	while (my ($k,$v) = each %$data)
 	{
 		$self{$k} = $v;
 	}
 
-	$meta ||= {};
-	while (my ($k,$v) = each %$meta)
-	{
-		$meta->{$k} = $v;
-	}
-
 	return $self;
 }
 
 	return { %{ $_[0] } };
 }
 
-sub nodePath   { return _meta('nodePath', @_); }
+sub nodeIndex  { return _meta('nodeIndex', @_); }
 sub rootNode   { return _meta('rootNode', @_); }
 sub parentNode { return _meta('parentNode', @_); }
 
+sub nodePath
+{
+	my ($self, $style) = @_;
+	$style ||= 'jsonpath';
+	
+	Carp::croak "Don't know style: $style\n"
+		unless $style =~ /^jsonpath$/i;
+	
+	if ($self == $self->rootNode)
+	{
+		return '$';
+	}
+	else
+	{
+		my $index = $self->parentNode->typeof eq 'ARRAY' 
+			? ('[' . $self->nodeIndex . ']')
+			: ("['" . $self->nodeIndex . "']");
+		return $self->parentNode->nodePath($style) . $index;
+	}
+}
+
 1;
 
 package JSON::JOM::Object::Tie;
 	if (defined $new)
 	{
 		my $old = jsonobj $_[0];
-		$new->nodePath( $old->nodePath . '[' . $_[1] . ']' );
+		$new->nodeIndex($_[1]);
 		$new->parentNode($old);
 		$new->rootNode($old->rootNode);
 		$value = $new;