File Coverage

blib/lib/Paws/DynamoDB/Response/Parser.pm
Criterion Covered Total %
statement 62 66 93.9
branch 29 38 76.3
condition 9 20 45.0
subroutine 10 10 100.0
pod 2 2 100.0
total 112 136 82.3


line stmt bran cond sub pod time code
1             package Paws::DynamoDB::Response::Parser;
2              
3             $Paws::DynamoDB::Response::Parser::VERSION = '0.06';
4             $Paws::DynamoDB::Response::Parser::AUTHORITY = 'cpan:MANWAR';
5              
6 2     2   234472 use strict;
  2         26  
  2         78  
7 2     2   10 use warnings;
  2         4  
  2         96  
8 2     2   1241 use Data::Dumper;
  2         19898  
  2         241  
9 2     2   22 use Carp qw(croak);
  2         5  
  2         139  
10 2     2   16 use Scalar::Util qw(blessed);
  2         5  
  2         2003  
11              
12             =head1 NAME
13              
14             Paws::DynamoDB::Response::Parser - Convert Paws DynamoDB response objects to Perl data structures.
15              
16             =head1 SYNOPSIS
17              
18             use Paws;
19             use Paws::DynamoDB::Response::Parser;
20              
21             my $parser = Paws::DynamoDB::Response::Parser->new;
22             my $dynamodb = Paws->service('DynamoDB',
23             region => 'eu-west-1',
24             endpoint => 'http://localhost:4566'
25             );
26             my $response = $dynamodb->Scan(TableName => "Users");
27             my $result = $parser->to_perl($response);
28              
29             =head1 DESCRIPTION
30              
31             While working on the blog post for L, I had trouble
32             decoding the response. This is the solution to the trouble I was facing.
33              
34             This module converts the following response objects into native Perl data structures,
35             handling all C attribute types (S, N, B, M, L etc.).
36              
37             =over 4
38              
39             =item Paws::DynamoDB::GetItemOutput
40              
41             =item Paws::DynamoDB::ScanOutput
42              
43             =item Paws::DynamoDB::QueryOutput
44              
45             =item Paws::DynamoDB::BatchGetItemOutput
46              
47             =back
48              
49             =cut
50              
51             =head1 METHODS
52              
53             =head2 new()
54              
55             Creates a new parser instance.
56              
57             =cut
58              
59             sub new {
60 1     1 1 233681 my ($class) = @_;
61 1         6 return bless {}, $class;
62             }
63              
64             =head2 to_perl($response)
65              
66             Converts Paws DynamoDB response object to a Perl data structure.
67              
68             Supported response types:
69              
70             =over 4
71              
72             =item - GetItemOutput
73              
74             =item - ScanOutput
75              
76             =item - QueryOutput
77              
78             =item - BatchGetItemOutput
79              
80             =back
81              
82             =cut
83              
84             sub to_perl {
85 4     4 1 18782 my ($self, $response) = @_;
86              
87 4 50       23 unless (blessed($response)) {
88 0         0 croak "Invalid response object";
89             }
90              
91 4 100 100     16 if ($response->isa('Paws::DynamoDB::GetItemOutput')) {
    100          
    50          
92 1 50       37 return $response->Item ? $self->_unwrap_item($response->Item) : undef;
93             }
94             elsif ($response->isa('Paws::DynamoDB::ScanOutput') ||
95             $response->isa('Paws::DynamoDB::QueryOutput')) {
96 2   50     135 my $items = $response->Items || [];
97 2         176 return [ map { $self->_unwrap_item($_) } @$items ];
  2         11  
98             }
99             elsif ($response->isa('Paws::DynamoDB::BatchGetItemOutput')) {
100 1         88 return $self->_process_batch_response($response);
101             }
102              
103 0         0 croak "Unsupported response type: " . ref($response);
104             }
105              
106             #
107             #
108             # PRIVATE SUBROUTINES
109              
110             sub _process_batch_response {
111 1     1   3 my ($self, $response) = @_;
112              
113 1         3 my @all_items;
114              
115 1 50 33     77 if ($response->Responses && blessed($response->Responses)) {
116 1         194 my $responses_map = $response->Responses->Map;
117 1         219 foreach my $table_name (keys %$responses_map) {
118 1         3 my $table_items = $responses_map->{$table_name};
119 1 50       6 if (ref $table_items eq 'ARRAY') {
120 1         4 push @all_items, map { $self->_unwrap_item($_) } @$table_items;
  1         5  
121             }
122             }
123             }
124              
125 1         6 return \@all_items;
126             }
127              
128             sub _unwrap_item {
129 4     4   178 my ($self, $item) = @_;
130 4 50 33     34 return undef unless defined $item
      33        
131             && blessed($item)
132             && $item->isa('Paws::DynamoDB::AttributeMap');
133              
134 4         81 my %unwrapped;
135 4         63 my $item_map = $item->Map;
136 4         373 foreach my $key (keys %$item_map) {
137 36         1953 $unwrapped{$key} = $self->_unwrap_attribute($item_map->{$key});
138             }
139 4         53 return \%unwrapped;
140             }
141              
142             sub _unwrap_attribute {
143 48     48   441 my ($self, $attr) = @_;
144              
145 48 50 33     509 return undef unless defined $attr
      33        
146             && blessed($attr)
147             && $attr->isa('Paws::DynamoDB::AttributeValue');
148              
149 48 100       1141 if (defined $attr->S) { return $attr->S; }
  8 100       690  
    100          
    100          
    50          
    100          
    100          
    100          
    100          
    50          
150 8         1368 elsif (defined $attr->N) { return $attr->N + 0; }
151 8         1849 elsif (defined $attr->BOOL) { return $attr->BOOL; }
152 4         2067 elsif (defined $attr->NULL) { return undef; }
153 0         0 elsif (defined $attr->B) { return $attr->B; }
154             elsif (defined $attr->M) {
155 4         1752 my %map;
156 4         7 foreach my $key (keys %{$attr->M}) {
  4         36  
157 4         1925 $map{$key} = $self->_unwrap_attribute($attr->M->{$key});
158             }
159 4         252 return \%map;
160             }
161             elsif (defined $attr->L) {
162 4         1926 return [ map { $self->_unwrap_attribute($_) } @{$attr->L} ];
  8         773  
  4         21  
163             }
164 4         2435 elsif (defined $attr->SS) { return $attr->SS; }
165 4         2832 elsif (defined $attr->NS) { return [ map { $_ + 0 } @{$attr->NS} ]; }
  8         317  
  4         28  
166 4         4423 elsif (defined $attr->BS) { return $attr->BS; }
167              
168 0           croak "Unsupported attribute type: " . Dumper($attr);
169             }
170              
171             =head1 AUTHOR
172              
173             Mohammad Sajid Anwar
174              
175             =head1 REPOSITORY
176              
177             L
178              
179             =head1 BUGS
180              
181             Please report any bugs or feature requests through the web interface at L.
182             I will be notified and then you'll automatically be notified of progress on your
183             bug as I make changes.
184              
185             =head1 SUPPORT
186              
187             You can find documentation for this module with the perldoc command.
188              
189             perldoc Paws::DynamoDB::Response::Parser
190              
191             You can also look for information at:
192              
193             =over 4
194              
195             =item * BUG Report
196              
197             L
198              
199             =item * CPAN Ratings
200              
201             L
202              
203             =item * Search MetaCPAN
204              
205             L
206              
207             =back
208              
209             =head1 LICENSE AND COPYRIGHT
210              
211             Copyright (C) 2025 Mohammad Sajid Anwar.
212              
213             This program is free software; you can redistribute it and / or modify it under
214             the terms of the the Artistic License (2.0). You may obtain a copy of the full
215             license at:
216              
217             L
218              
219             Any use, modification, and distribution of the Standard or Modified Versions is
220             governed by this Artistic License.By using, modifying or distributing the Package,
221             you accept this license. Do not use, modify, or distribute the Package, if you do
222             not accept this license.
223              
224             If your Modified Version has been derived from a Modified Version made by someone
225             other than you,you are nevertheless required to ensure that your Modified Version
226             complies with the requirements of this license.
227              
228             This license does not grant you the right to use any trademark, service mark,
229             tradename, or logo of the Copyright Holder.
230              
231             This license includes the non-exclusive, worldwide, free-of-charge patent license
232             to make, have made, use, offer to sell, sell, import and otherwise transfer the
233             Package with respect to any patent claims licensable by the Copyright Holder that
234             are necessarily infringed by the Package. If you institute patent litigation
235             (including a cross-claim or counterclaim) against any party alleging that the
236             Package constitutes direct or contributory patent infringement,then this Artistic
237             License to you shall terminate on the date that such litigation is filed.
238              
239             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND
240             CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
241             WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
242             NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS
243             REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT,
244             INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
245             OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
246             =head1 LICENSE
247              
248             =cut
249              
250             1; # End of Paws::DynamoDB::Response::Parser
251