File Coverage

blib/lib/LWP/JSON/Tiny.pm
Criterion Covered Total %
statement 31 31 100.0
branch 2 2 100.0
condition 3 6 50.0
subroutine 10 10 100.0
pod 2 2 100.0
total 48 51 94.1


line stmt bran cond sub pod time code
1             package LWP::JSON::Tiny;
2              
3 5     5   34 use strict;
  5         11  
  5         115  
4 5     5   21 use warnings;
  5         10  
  5         108  
5 5     5   21 no warnings 'uninitialized';
  5         9  
  5         117  
6              
7 5     5   302 use HTTP::Request::JSON;
  5         11  
  5         120  
8 5     5   1269 use HTTP::Response::JSON;
  5         13  
  5         131  
9 5     5   1581 use JSON::MaybeXS;
  5         17780  
  5         223  
10 5     5   2156 use LWP;
  5         64372  
  5         158  
11 5     5   1057 use LWP::UserAgent::JSON;
  5         11  
  5         671  
12              
13             # Have you updated the version number in the POD below?
14             our $VERSION = '0.013';
15             $VERSION = eval $VERSION;
16              
17             =head1 NAME
18              
19             LWP::JSON::Tiny - use JSON natively with LWP objects
20              
21             =head1 VERSION
22              
23             This is version 0.013.
24              
25             =head1 SYNOPSIS
26              
27             my $user_agent = LWP::UserAgent::JSON->new;
28             my $request = HTTP::Request::JSON->new(POST => "$url_prefix/upload_dance");
29             $request->json_content({ contents => [qw(badger mushroom snake)] });
30             my $response = $user_agent->request($request);
31             if (my $upload_id = $response->json_content->{upload}{id}) {
32             print "Uploaded Weebl rip-off: $upload_id\n";
33             }
34              
35             my $other_response = $some_other_object->do_stuff(...);
36             if (LWP::UserAgent::JSON->rebless_maybe($other_response)) {
37             do_something($other_response->json_content);
38             }
39              
40             =head1 DESCRIPTION
41              
42             A lot of RESTful API integration involves pointless busy work with setting
43             accept and content-type headers, remembering how Unicode is supposed to work
44             and so on. This is a very simple wrapper around HTTP::Request and
45             HTTP::Response that handles all of that for you.
46              
47             There are four classes in this distribution:
48              
49             =over
50              
51             =item LWP::JSON::Tiny
52              
53             Pulls in the other classes, and implements a L method which
54             returns a JSON object, suitable for parsing and emitting JSON.
55              
56             =item HTTP::Request::JSON
57              
58             A subclass of HTTP::Request. It automatically sets the Accept header to
59             C, and implements a
60             L method
61             which takes a JSONable data structure and sets the content-type.
62              
63             =item HTTP::Response::JSON
64              
65             A subclass of HTTP::Response. It implements a
66             L method which
67             decodes the JSON contents into a Perl data structure.
68              
69             =item LWP::UserAgent::JSON
70              
71             A subclass of LWP::UserAgent. It does only one thing: is a response has
72             content-type JSON, it reblesses it into a HTTP::Response::JSON object.
73             It exposes this method L
74             for convenience, if you ever get an HTTP::Response object back from some
75             other class.
76              
77             =back
78              
79             As befits a ::Tiny distribution, sensible defaults are applied. If you really
80             need to tweak this stuff (e.g. you really care about the very slight
81             performance impact of sorting all hash keys), look at the individual
82             modules' documentation for how you can subclass behaviour.
83              
84             =head2 Class methods
85              
86             =head3 json_object
87              
88             Out: $json
89              
90             Returns a JSON object, as per JSON::MaybeXS->new. Cached across multiple
91             calls for speed.
92              
93             Note that the JSON object has the utf8 option disabled. I.
94             The documentation for JSON::XS is very clear that the utf8 option means both
95             that it should spit out JSON in UTF8, and that it should expect strings
96             passed to it to be in UTF8 encoding. This latter part is daft, and violates
97             the best practice that character encoding should be dealt with at the
98             outermost layer.
99              
100             =cut
101              
102             {
103             my %json_by_class;
104              
105             sub json_object {
106 33     33 1 85 my ($invocant) = @_;
107              
108 33   33     145 my $class = ref($invocant) || $invocant;
109 33   66     165 my $json ||= $json_by_class{$class};
110 33 100       111 return $json if defined $json;
111 6         27 $json = JSON::MaybeXS->new($class->default_json_arguments);
112 6         233 return $json_by_class{$class} = $json;
113             }
114             }
115              
116             =head3 default_json_arguments
117              
118             Out: %default_json_arguments
119              
120             The default arguments to pass to JSON::MaybeXS->new. This is what you'd
121             subclass if you wanted to change how LWP::JSON::Tiny encoded JSON.
122              
123             =cut
124              
125             sub default_json_arguments {
126             return (
127 6     6 1 63 utf8 => 0,
128             allow_nonref => 1,
129             allow_unknown => 0,
130             allow_blessed => 0,
131             convert_blessed => 0,
132             canonical => 1,
133             );
134             }
135              
136             =head1 SEE ALSO
137              
138             L handles authentication and common URL prefixes, but (a)
139             doesn't support PATCH routes, and (b) makes you use a wrapper object
140             rather than LWP directly.
141              
142             L handles authentication (including favours of OAuth), common URL
143             prefixes, response data structure transformations, but has the same
144             limitations as JSON::API, as well as being potentially unwieldy.
145              
146             L decodes JSON but makes you use a wrapper object, and
147             looks like a half-hearted attempt that never went anywhere.
148              
149             =head1 AUTHOR
150              
151             Sam Kington
152              
153             The source code for this module is hosted on GitHub
154             L - this is probably the
155             best place to look for suggestions and feedback.
156              
157             =head1 COPYRIGHT
158              
159             Copyright (c) 2015-2017 Sam Kington.
160              
161             =head1 LICENSE
162              
163             This library is free software and may be distributed under the same terms as
164             perl itself.
165              
166             =cut
167              
168             1;