File Coverage

blib/lib/MARC/Record/MiJ.pm
Criterion Covered Total %
statement 83 83 100.0
branch 6 6 100.0
condition n/a
subroutine 19 19 100.0
pod 10 10 100.0
total 118 118 100.0


line stmt bran cond sub pod time code
1             package MARC::Record::MiJ;
2 1     1   989 use ex::monkeypatched;
  1         14337  
  1         9  
3 1     1   1347 use JSON;
  1         38266  
  1         6  
4 1     1   190 use 5.006;
  1         4  
  1         37  
5 1     1   5 use strict;
  1         2  
  1         33  
6 1     1   6 use warnings FATAL => 'all';
  1         1  
  1         1070  
7              
8             =head1 NAME
9              
10             MARC::Record::MiJ - Convert MARC::Record to/from marc-in-json structure
11              
12             =head1 VERSION
13              
14             Version 0.04
15              
16             =cut
17              
18             our $VERSION = '0.04';
19              
20             =head1 SYNOPSIS
21              
22             use MARC::Record;
23             use MARC::Record::MIJ
24              
25             my $str = get_marc_in_json_from_somewhere;
26              
27             # The most common use will be to use methods monkeypatched into MARC::Record
28             my $r = MARC::Record->new_from_mij($str);
29             my $json = $r->to_mij;
30              
31             # You can also work with the underlying hash/array structure if you're dealing with
32             # json serialization/deserialization on your own
33              
34             my $mij_structure = $r->to_mij_structure;
35             my $r = MARC::Record->new_from_mij_structure($mij_structure);
36              
37             # You can also call things on MARC::Record::MiJ
38              
39             my $r = MARC::Record::MiJ->new($str);
40             my $json = MARC::Record::MiJ->to_mij($r);
41             my $mij_structure = MARC::Record::MiJ->to_mij_structure($r);
42             my $r = MARC::Record::MiJ->new_from_mij_structure($mij_structure);
43              
44             =head1 DESCRIPTION
45              
46             Reads and writes MARC-in-JSON structures and strings as supported by pymarc/ruby-marc/marc4j and
47             described at http://dilettantes.code4lib.org/blog/2010/09/a-proposal-to-serialize-marc-in-json/
48              
49             Don't confuse with another (incompatible) JSON encoding in the module C, which
50             to the best of my knowledge isn't supported by other readers/writers.
51              
52             For reading, you probably don't need to use this directly; take a look at C for reading in
53             newline-delimited marc-in-json files by itself or in conjunction with C.
54              
55             The MARC::Record distribution doesn't so much do do writing out files. You can do something like this:
56              
57             # convert file from marc binary to marc-in-json
58             use MARC::Batch;
59             use MARC::Record::MiJ;
60             my $batch = MARC::Batch->new('USMARC', 'file.mrc');
61             open(my $jsonfile, '>', 'file.ndj' );
62             while (my $r = $batch->next) {
63             print $jsonfile MARC::Record::MiJ->to_mij($r), "\n";
64             }
65             close $jsonfile;
66              
67             ...to produce newline-delimited marc-in-json from a binary file.
68              
69              
70             =head1 SUBROUTINES/METHODS
71              
72             =head2 json
73              
74             Get a json object to work with (memoized). We want to control it so we make sure
75             it's not doing anything pretty (like, say, putting newlines in, which woudl make it
76             harder to produce newline-delimited json file).
77              
78             =cut
79              
80             my $json;
81             sub json {
82 23 100   23 1 1863 return $json if ($json);
83 1         2 my $self = shift;
84 1         24 $json = JSON->new->utf8;
85 1         9 $json->pretty(0);
86 1         6 return $json;
87             }
88              
89              
90             =head2 new($str)
91              
92             Take a JSON string and turn it into a MARC::Record object
93              
94             =cut
95              
96             sub new {
97 11     11 1 34 my $self = shift;
98 11         29 my $str = shift;
99 11         42 return $self->new_from_mij_structure($self->json->decode($str));
100             }
101              
102             =head2 to_mij($r)
103              
104             Take a record; return a JSON string
105              
106             =cut
107              
108             sub to_mij {
109 10     10 1 61002 my $self = shift;
110 10         18 my $r = shift;
111 10         27 return $self->json->encode($self->to_mij_structure($r));
112             }
113              
114              
115              
116             =head2 MARC::Record::JSON->to_mij_structure($r)
117              
118             Turn a record into a marc-in-json compatible hash; return the hash pointer
119              
120             =cut
121              
122             sub to_mij_structure {
123 14     14 1 81924 my $class = shift;
124 14         25 my $r = shift;
125            
126 14         24 my $h = {};
127 14         21 my @fields;
128 14         70 $h->{leader} = $r->leader;
129            
130 14         180 foreach my $f ($r->fields) {
131 410 100       4609 if ($f->is_control_field) {
132 65         433 push @fields, controlfield_to_mij_structure($f);
133             } else {
134 345         1881 push @fields, valuefield_to_mij_structure($f);
135             }
136             }
137 14         147 $h->{fields} = \@fields;
138 14         3497 return $h;
139             }
140              
141              
142             =head2 controlfield_to_mij_structure($field)
143              
144             Turn a MARC::Record controlfield into an appropriate hash
145              
146             =cut
147              
148             sub controlfield_to_mij_structure {
149 65     65 1 156 my $cf = shift;
150 65         224 return {$cf->tag => $cf->data };
151             }
152              
153             =head2 valuefield_to_mij_structure($field)
154              
155             Turn a MARC::Record valuefield into an appropriate hash
156              
157              
158             =cut
159              
160             sub valuefield_to_mij_structure {
161 345     345 1 418 my $vf = shift;
162 345         434 my @subfields;
163 345         993 my $h = {ind1=>$vf->indicator(1), ind2=>$vf->indicator(2)};
164 345         7984 foreach my $sf ($vf->subfields) {
165 638         11659 push @subfields, subfield_to_mij_structure($sf);
166             }
167 345         1177 $h->{subfields} = \@subfields;
168 345         1509 return {$vf->tag => $h};
169            
170             }
171              
172             =head2 subfield_to_mij_structure($sf)
173              
174             Turn a MARC::Record subfield pair (arrayref duple of code/value) into an appropriate hash
175              
176              
177             =cut
178              
179             sub subfield_to_mij_structure {
180 638     638 1 787 my $sf = shift;
181 638         3658 return {$sf->[0]=> $sf->[1]};
182             }
183              
184              
185             =head2 my $r = MARC::Record::JSON->new_from_mij_structure($mij_structure)
186              
187             Given a marc-in-json structure, return a MARC::Record object
188              
189             =cut
190              
191             sub new_from_mij_structure {
192 14     14 1 1646 my $self = shift;
193 14         31 my $h = shift;
194            
195 14         82 my $r = new MARC::Record;
196            
197 14         244 $r->leader($h->{leader});
198            
199 14         189 my @fields;
200 14         22 foreach my $f (@{$h->{fields}}) {
  14         50  
201 427         23878 push @fields, new_field_from_mij_structure($f);
202             }
203 14         1043 $r->append_fields(@fields);
204 14         1207 return $r;
205             }
206              
207             =head2 new_field_from_mij_structure($f)
208              
209             Given a field structure, create an appropriate (control or variable) field
210              
211             =cut
212              
213             sub new_field_from_mij_structure {
214 427     427 1 611 my $mijf = shift;
215 427         492 my ($tag, $h);
216              
217              
218 427         2066 while (my ($k, $v) = each(%$mijf)) {
219 427         716 $tag = $k;
220 427         4171 $h = $v;
221             }
222            
223 427 100       1047 if (ref($h)) { # if it's a hashref
224 361         785 return new_datafield_from_mij_structure($tag, $h);
225             } else { # create and return a control field
226 66         252 return MARC::Field->new($tag, $h);
227             }
228              
229             }
230              
231             =head2 new_datafield_from_mij_structure
232              
233             Support for new_field_from_mij_structure; do the more complex work
234             of creating a datafield
235              
236             =cut
237              
238             sub new_datafield_from_mij_structure {
239 361     361 1 562 my ($tag, $h) = @_;
240 361         13125 my @subfields;
241 361         470 foreach my $sf (@{$h->{subfields}}) {
  361         943  
242 677         6275 while (my ($code, $data) = each %$sf) {
243 677         4421 push @subfields, $code, $data
244             }
245             }
246 361         1631 return MARC::Field->new($tag, $h->{ind1}, $h->{ind2}, @subfields);
247              
248             }
249              
250             =head1 Monkeypatching MARC::Record
251              
252             Add C to MARC::Record
253              
254             my $r = MARC::Record->new_from_mij_structure($mij_structure);
255             $mij_structure = $r->to_mij_structure;
256              
257             =cut
258              
259             ex::monkeypatched->inject('MARC::Record' =>
260 2     2   5 new_from_mij_structure => sub { my $class = shift; my $mij = shift; return
  2         4  
261 2         7 MARC::Record::MiJ->new_from_mij_structure($mij)},
262 2     2   33687 to_mij_structure => sub { my $self = shift; return MARC::Record::MiJ->to_mij_structure($self) },
  2         14  
263 1     1   4 new_from_mij => sub { my $class = shift; my $mij = shift; return MARC::Record::MiJ->new($mij) },
  1         22  
  1         6  
264 1     1   3 to_mij => sub { my $self = shift; return MARC::Record::MiJ->to_mij($self) }
  1         9  
265            
266             );
267              
268              
269              
270             =head1 AUTHOR
271              
272             Bill Dueber, C<< >>
273              
274             =head1 BUGS
275              
276             Please report any bugs or feature requests to C, or through
277             the web interface at L. I will be notified, and then you'll
278             automatically be notified of progress on your bug as I make changes.
279              
280              
281              
282              
283             =head1 SUPPORT
284              
285             You can find documentation for this module with the perldoc command.
286              
287             perldoc MARC::Record::MiJ
288              
289              
290             You can also look for information at:
291              
292             =over 4
293              
294             =item * RT: CPAN's request tracker (report bugs here)
295              
296             L
297              
298             =item * AnnoCPAN: Annotated CPAN documentation
299              
300             L
301              
302             =item * CPAN Ratings
303              
304             L
305              
306             =item * Search CPAN
307              
308             L
309              
310             =back
311              
312              
313             =head1 ACKNOWLEDGEMENTS
314              
315              
316             =head1 LICENSE AND COPYRIGHT
317              
318             Copyright 2013 Bill Dueber.
319              
320             This software is free software and may be distributed under the same
321             terms as Perl itself.
322              
323              
324             =cut
325              
326             1; # End of MARC::Record::MiJ