##-*- Mode: CPerl -*-
##
## File: Tie/File/Indexed/JSON.pm
## Author: Bryan Jurish <moocow@cpan.org>
## Description: tied array access to indexed data files: JSON-encoded data structures
use JSON;
use strict;
##======================================================================
## Globals
our @ISA = qw(Tie::File::Indexed);
##======================================================================
## Constructors etc.
## $tfi = CLASS->new(%opts)
## $tfi = CLASS->new($file,%opts)
## + new %opts, object structure:
## (
## json => $json, ##-- JSON object or HASH-ref of options
## )
## \%defaults = CLASS_OR_OBJECT->defaults()
## + default attributes for constructor
sub defaults {
return (
$_[0]->SUPER::defaults,
json => {utf8=>1, relaxed=>1, allow_nonref=>1, allow_unknown=>1, allow_blessed=>1, convert_blessed=>1, pretty=>0, canonical=>0},
);
}
##--------------------------------------------------------------
## Utilities: JSON
## $json = $aj->json()
## + returns json codec
sub json {
return $_[0]{json} if (UNIVERSAL::isa($_[0]{json}, 'JSON'));
my $json = JSON->new;
foreach (grep {$json->can($_)} keys %{$_[0]{json}//{}}) {
$json->can($_)->($json,$_[0]{json}{$_});
}
return $_[0]{json} = $json;
}
##======================================================================
## Object API: overrides
##--------------------------------------------------------------
## Object API: overrides: open/close
## $tfi_or_undef = $tfi->open($file,$mode)
## $tfi_or_undef = $tfi->open($file)
## $tfi_or_undef = $tfi->open()
## + opens file(s)
sub open {
my $tfi = shift;
return undef if (!$tfi->SUPER::open(@_));
##-- ensure 'json' object is defined
$tfi->json();
return $tfi;
}
##======================================================================
## Subclass API: Data I/O
## $bool = $tfi->writeData($utf8_string)
## + override transparently encodes $data using the JSON module
sub writeData {
return 1 if (!defined($_[1])); ##-- don't waste space on undef
return $_[0]{datfh}->print( $_[0]{json}->encode($_[1]) );
}
## $data_or_undef = $tfi->readData($length)
## + override decodes stored data using the JSON module
sub readData {
return undef if ($_[1]==0 || !defined(my $buf=$_[0]->SUPER::readData($_[1])));
return $_[0]{json}->decode($buf);
}
1; ##-- be happpy