File Coverage

blib/lib/Catmandu/Fix/get_json.pm
Criterion Covered Total %
statement 49 49 100.0
branch 14 14 100.0
condition n/a
subroutine 11 11 100.0
pod 0 2 0.0
total 74 76 97.3


line stmt bran cond sub pod time code
1             package Catmandu::Fix::get_json;
2              
3             our $VERSION = '0.51';
4              
5 1     1   54693 use Catmandu::Sane;
  1         154149  
  1         7  
6 1     1   297 use Catmandu::Util;
  1         2  
  1         34  
7 1     1   6 use Moo;
  1         2  
  1         5  
8 1     1   796 use Catmandu::Fix::Has;
  1         750  
  1         5  
9 1     1   950 use Catmandu::Importer::getJSON;
  1         6  
  1         949  
10              
11             with "Catmandu::Fix::Base";
12              
13             has url => ( fix_arg => 1, default => sub { "url" } );
14              
15             has dry => ( fix_opt => 1 );
16             has cache => ( fix_opt => 1 );
17             has timeout => ( fix_opt => 1, default => sub { 10 } );
18             has agent => ( fix_opt => 1 );
19             has proxy => ( fix_opt => 1 );
20             has wait => ( fix_opt => 1 );
21              
22             has vars => ( fix_opt => 1 );
23             has path => ( fix_opt => 1 );
24              
25             has importer => ( is => 'ro', lazy => 1, builder => 1 );
26              
27             sub _build_importer {
28 12     12   80 my ($self) = @_;
29              
30 12         85 my %options = (
31             dry => $self->dry,
32             cache => $self->cache,
33             timeout => $self->timeout,
34             agent => $self->agent,
35             proxy => $self->proxy,
36             wait => $self->wait,
37             );
38              
39             # URL template or plain URL
40 12 100       67 if ( $self->url =~ qr{^https?://} ) {
41 8 100       29 $options{ $self->vars ? 'url' : 'from' } = $self->url;
42             }
43 12         203 Catmandu::Importer::getJSON->new(%options);
44             }
45              
46             sub BUILD {
47 12     12 0 71 my ($self) = @_;
48 12 100       77 unless ( defined $self->path ) {
49 8 100       114 $self->{path} = $self->url =~ qr{^https?://} ? '' : $self->url;
50             }
51             }
52              
53             sub emit {
54 12     12 0 3580 my ( $self, $fixer ) = @_;
55 12         39 my $path = $fixer->split_path( $self->path );
56 12         413 my $importer = $fixer->capture( $self->importer );
57              
58             # plain URL
59 12 100       485 if ( $self->importer->from ) {
60             return $fixer->emit_create_path(
61             $fixer->var,
62             $path,
63             sub {
64 3     3   141 sprintf '%s = %s->request(%s->from) // { };',
65             shift, $importer, $importer;
66             }
67 3         60 );
68             }
69              
70             # URL template or base URL
71 9 100       160 if ( $self->importer->url ) {
72 5         151 my $tpl = $fixer->split_path( $self->vars );
73 5         106 my $url = $fixer->generate_var;
74              
75             return $fixer->emit_create_path(
76             $fixer->var,
77             $tpl,
78             sub {
79 5     5   222 my $tpl = shift;
80             "my $url;"
81             . "if (is_hash_ref($tpl) or is_string($tpl) and $tpl !~ qr{^https?://}) {"
82             . " $url = ${importer}->construct_url($tpl) " . "}"
83             . $fixer->emit_create_path(
84             $fixer->var,
85             $path,
86             sub {
87 5         100 sprintf '%s = %s ? %s->request(%s) // {} : {};',
88             shift, $url, $importer, $url;
89             }
90 5         94 );
91             }
92 5         99 );
93             }
94              
95             # URL from field
96 4         83 my $url = $fixer->split_path( $self->url );
97              
98             return $fixer->emit_create_path(
99             $fixer->var,
100             $url,
101             sub {
102 4 100   4   171 if ( $self->vars ) {
103 3         4 my $base = shift;
104 3         8 my $tpl = $fixer->split_path( $self->vars );
105 3         58 my $url = $fixer->generate_var;
106              
107             return $fixer->emit_create_path(
108             $fixer->var,
109             $tpl,
110             sub {
111 3         112 my $tpl = shift;
112             "my $url;"
113             . "if (is_hash_ref($tpl) or is_string($tpl) and $tpl !~ qr{^https?://}) {"
114             . " $url = ${importer}->construct_url($base, $tpl); "
115             . "}"
116             . $fixer->emit_create_path(
117             $fixer->var,
118             $path,
119             sub {
120 3         67 sprintf '%s = %s ? %s->request(%s) // {} : {};',
121             shift, $url, $importer, $url;
122             }
123 3         58 );
124             }
125 3         60 );
126             }
127             else {
128 1         2 my $url = shift;
129             return $fixer->emit_create_path(
130             $fixer->var,
131             $path,
132             sub {
133 1         49 sprintf '%s = %s->request(%s) // { };',
134             shift, $importer, $url;
135             }
136 1         17 );
137             }
138             }
139 4         129 );
140              
141             }
142              
143             1;
144             __END__
145              
146             =head1 NAME
147              
148             Catmandu::Fix::get_json - get JSON data from an URL as fix function
149              
150             =head1 SYNOPSIS
151              
152             # fetches a hash or array
153             get_json("http://example.com/json")
154              
155             # stores it in path.key
156             get_json("http://example.com/json", path: path.key)
157              
158             # add URL query parameters or URL path from config
159             get_json("http://example.com/", vars: config)
160              
161             # fill URL template fields from config
162             get_json("http://example.com/{name}.json", vars: config)
163              
164             # get URL or URL template from a field
165             get_json(field.name)
166            
167             =head1 DESCRIPTION
168              
169             This L<Catmandu::Fix> provides a method to fetch JSON data from an URL. The
170             response is added as new item or to a field of the current item.
171              
172             =head1 OPTIONS
173              
174             The first argument must be an URL, an URL template, or a field where to take
175             an URL or URL template from. Additional options include:
176              
177             =over
178              
179             =item path
180              
181             Field to store result JSON in. If not given or set to the empty string, the
182             whole item is replaced by the fetched JSON response. If the first argument is a
183             field, the same field is used as C<path> by default.
184              
185             =item vars
186              
187             Field to get URL template variables, URL query parameters or an URL path
188             expression from. This option is required if the first argument is an URL
189             template.
190              
191             =back
192              
193             The fix function also supports options C<dry>, C<cache>, C<timeout>, C<agent>,
194             C<proxy>, and C<wait> as documented in L<Catmandu::Importer::getJSON>. Options
195             C<client>, C<headers>, and C<warn> are not supported.
196              
197             =cut