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