ataService::JSON
#
# This module is responsible for putting data responses into JSON format.
#
# Author: Michael McClennen
use strict;
package Web::DataService::Plugin::JSON;
use JSON;
use Encode
;
use parent 'Exporter';
our @EXPORT_OK = qw(json_list_value json_clean);
# emit_header ( request, field_list )
#
# Return the initial text of a JSON result.
sub emit_header {
my ($class, $
foreach my $key ( $request->datainfo_keys )
{
next unless $info->{$key};
my $value = json_clean($info->{$key});
$output .= qq{"$key":$value,\n};
}
$output .= '"parameters":
value is
itself a hashref, and if the selected output format can express hierarchical
data (e.g. JSON). In that case, the hashref will be interpreted as a
sub-record according to the specified block
is element will always be
included in the output even if its value is undefined. By default, the JSON
format omits from each record any fields whose values are undefined. Custom
output formats may d
rmat is XML.
=head3 show_as_list
This attribute is only used when the selected output format is JSON. If it is
given a true value, then this output element will be represented as an array
even if t
F<formats_doc.tt>.
The template corresponding to C<formats/json> is F<formats/json_doc.tt>, but
it could also have been called F<formats/json/index.tt>. If no matching
template file is not found, the
ation page for that node. For example:
L<special parameters|node:special>
L<JSON format|node:formats/json>
=item op:
When a link is encountered with this prefix, the remainder is parsed to
o auto-generate a URL that will carry out the specified operation. For
example:
L<op:single.json?state=WI>
L<the list of regions|op:regions.txt>
=item path:
When a link is encountered with
t.
package Web::DataService::IRequest;
use Carp 'croak';
use Scalar::Util 'reftype';
use JSON 'decode_json';
use Try::Tiny;
use Moo::Role;
# has_block ( block_key_or_name )
#
# Return true if t
decoded_body};
}
# If the body starts and ends with '{' or '[', assume the format is JSON regardless of content type.
elsif ( $request->{raw_body} =~ / ^ [{] .* [}] $ | ^ [\[] .*
quest->{decoded_body} )
{
# print STDERR "About to decode\n";
$request->{decoded_body} = JSON->new->utf8->relaxed->decode($request->{raw_body});
# print STDERR "Decoded: " . $request->{deco
the appropriate data using the backend data system and serializing the
output in a format such as JSON, CSV, or XML.
Using the methods provided by this module, you start by defining a set of data
ser
=item *
If the feature 'format_suffix' is active and the path ends in a format suffix
such as C<.json>, then that suffix is removed and later used to set the
"format" attribute of the request.
=item
url = $request->generate_url( { op => 'abc/def', format => 'json', params => 'foo=1' } );
$url = $request->generate_url( "op:abc/def.json?foo=1" );
The attributes are as follows:
=over
=item no
request body, if it is in a known format. Currently, the only two formats
understood are JSON and text. A JSON body will be decoded into a Perl data structure, while a text
body will be split into a
RMAT_CT) = (json => 'application/json',
txt => 'text/plain',
tsv => 'text/tab-separated-values',
csv => 'text/csv',
xml => 'text/xml');
our (%FORMAT_CLASS) = (json => 'Web::Da
taService::Plugin::JSON',
txt => 'Web::DataService::Plugin::Text',
tsv => 'Web::DataService::Plugin::Text',
csv => 'Web::DataService::Plugin::Text',
xml => 'Web::Da
|| $name eq 'csv';
$record->{is_text} //= 1 if $record->{content_type} =~ /(x(?:ht)?ml|text|json|javascript)/
|| $record->{encode_as_text};
croak "define_format: you must specify an
.
Assemble representations of data
=item 5.
Serialize those representations in formats such as JSON, XML, etc.
=item 6.
Set HTTP response headers
=item 7.
Generate appropriate error messages
=
installation includes two built-in serialization modules:
C<JSON>, which serializes responses using the
L<JSON|https://en.wikipedia.org/JSON> format, and C<Text>, which can generate
either tab-separat
prefixes, i.e. "/data1.0/my/operation.json" vs. "/data2.0/my/operation.json"
=item *
A version parameter, i.e. "/my/operation.json?v=1.0"
vs. "/my/operation.json?v=2.0"
=back
The section on L<VER
ng call will enable the formats 'json' and
'txt' with all of their default attribute values and documentation strings.
$ds->define_format(
{ name => 'json' },
{ name => 'txt' });
=> 'formats/json',
title => 'JSON format' },
{ path => 'formats/txt',
title => 'Plain text format' });
See the next section for descriptions of the various attributes.
=head4 json
This forma
sing
L<JSON|https://en.wikipedia.org/wiki/JSON> (JavaScript Object Notation). It
sets the content type of the response to "application/json", and its default
documentation node is "formats/json". Th
$ds->define_format(
{ name => 'json', content_type => 'application/json',
doc_node => 'formats/json', title => 'JSON',
default_vocab => 'com' },
"The JSON format is intended primarily to
Darwin Core element set.");
For example, the above call defines two response formats: one named 'json' and
the other named 'xml'. Each of these formats is defined by the set of
attributes contained
st with the URL path "/my/operation.json"
will select the operation corresponding to the data service node
"my/operation" and will render the output using the "json" format.
=head4 documentation
Thi
ing (optional)
=back
For example, the following string:
single.json?state=wi
will be parsed as: path="single", format="json", params="state=wi". These
elements are then used to construct a da
bug one of the example data
service operations:
perl -d bin/dataservice.pl GET /data1.0/list.json 'region=ne&show=total'
=head2 Diagnostics
The Web::DataService pacakge also enables some diagno
test the data service by sending some requests such as:
http://localhost:3000/data1.0/single.json?state=NY
http://localhost:3000/data1.0/list.txt?region=NE,MW&show=hist,total
Note: if you ar
to have a predefined breakpoint. For example:
perl -d bin/dataservice.pl GET /data1.0/list.json 'region=MW&show=total'
In lines 55-60, we generate a L<new instance|Web::DataService::Configurat
initions> that
will be available from this data service. In the case of this example, these are: JSON, comma-delimited text,
and tab-delimited text.
Lines 87-141 define a series of data service node
ns Web::DataService::Plugin::JSON and
# Web::DataService::Plugin::Text.
$ds->define_format(
{ name => 'json', doc_node => 'formats/json', title => 'JSON' },
"The JSON format is intended primaril
ath => '/',
title => 'Main Documentation',
public_access => 1,
default_format => 'json',
doc_default_template => 'doc_not_found.tt',
doc_default_op_template => 'operation.tt'
{ path => 'single',
title => 'Single state',
place => 1,
usage => [ "single.json?state=wi",
"single.txt?state=tx&show=hist&header=no" ],
output => 'basic',
optiona