1#!/opt/bin/perl 2 3=head1 NAME 4 5json_xs - JSON::XS commandline utility 6 7=head1 SYNOPSIS 8 9 json_xs [-v] [-f inputformat] [-t outputformat] 10 11=head1 DESCRIPTION 12 13F<json_xs> converts between some input and output formats (one of them is 14JSON). 15 16The default input format is C<json> and the default output format is 17C<json-pretty>. 18 19=head1 OPTIONS 20 21=over 4 22 23=item -v 24 25Be slightly more verbose. 26 27=item -f fromformat 28 29Read a file in the given format from STDIN. 30 31C<fromformat> can be one of: 32 33=over 4 34 35=item json - a json text encoded, either utf-8, utf16-be/le, utf32-be/le 36 37=item storable - a Storable frozen value 38 39=item storable-file - a Storable file (Storable has two incompatible formats) 40 41=item bencode - use Convert::Bencode, if available (used by torrent files, among others) 42 43=item clzf - Compress::LZF format (requires that module to be installed) 44 45=item eval - evaluate the given code as (non-utf-8) Perl, basically the reverse of "-t dump" 46 47=item yaml - YAML (avoid at all costs, requires the YAML module :) 48 49=item string - do not attempt to decode te file data 50 51=item none - nothing is read, creates an C<undef> scalar - mainly useful with C<-e> 52 53=back 54 55=item -t toformat 56 57Write the file in the given format to STDOUT. 58 59C<toformat> can be one of: 60 61=over 4 62 63=item json, json-utf-8 - json, utf-8 encoded 64 65=item json-pretty - as above, but pretty-printed 66 67=item json-utf-16le, json-utf-16be - little endian/big endian utf-16 68 69=item json-utf-32le, json-utf-32be - little endian/big endian utf-32 70 71=item storable - a Storable frozen value in network format 72 73=item storable-file - a Storable file in network format (Storable has two incompatible formats) 74 75=item bencode - use Convert::Bencode, if available (used by torrent files, among others) 76 77=item clzf - Compress::LZF format 78 79=item yaml - YAML 80 81=item dump - Data::Dump 82 83=item dumper - Data::Dumper 84 85=item string - writes the data out as if it were a string 86 87=item none - nothing gets written, mainly useful together with C<-e> 88 89Note that Data::Dumper doesn't handle self-referential data structures 90correctly - use "dump" instead. 91 92=back 93 94=item -e code 95 96Evaluate perl code after reading the data and before writing it out again 97- can be used to filter, create or extract data. The data that has been 98written is in C<$_>, and whatever is in there is written out afterwards. 99 100=back 101 102=head1 EXAMPLES 103 104 json_xs -t none <isitreally.json 105 106"JSON Lint" - tries to parse the file F<isitreally.json> as JSON - if it 107is valid JSON, the command outputs nothing, otherwise it will print an 108error message and exit with non-zero exit status. 109 110 <src.json json_xs >pretty.json 111 112Prettify the JSON file F<src.json> to F<dst.json>. 113 114 json_xs -f storable-file <file 115 116Read the serialised Storable file F<file> and print a human-readable JSON 117version of it to STDOUT. 118 119 json_xs -f storable-file -t yaml <file 120 121Same as above, but write YAML instead (not using JSON at all :) 122 123 json_xs -f none -e '$_ = [1, 2, 3]' 124 125Dump the perl array as UTF-8 encoded JSON text. 126 127 <torrentfile json_xs -f bencode -e '$_ = join "\n", map @$_, @{$_->{"announce-list"}}' -t string 128 129Print the tracker list inside a torrent file. 130 131 lwp-request http://cpantesters.perl.org/show/JSON-XS.json | json_xs 132 133Fetch the cpan-testers result summary C<JSON::XS> and pretty-print it. 134 135=head1 AUTHOR 136 137Copyright (C) 2008 Marc Lehmann <json@schmorp.de> 138 139=cut 140 141use strict; 142 143use Getopt::Long; 144use Storable (); 145use Encode; 146 147use JSON::XS; 148 149my $opt_verbose; 150my $opt_from = "json"; 151my $opt_to = "json-pretty"; 152my $opt_eval; 153 154Getopt::Long::Configure ("bundling", "no_ignore_case", "require_order"); 155 156GetOptions( 157 "v" => \$opt_verbose, 158 "f=s" => \$opt_from, 159 "t=s" => \$opt_to, 160 "e=s" => \$opt_eval, 161) or die "Usage: $0 [-v] -f fromformat [-e code] [-t toformat]\n"; 162 163my %F = ( 164 "none" => sub { undef }, 165 "string" => sub { $_ }, 166 "json" => sub { 167 my $enc = 168 /^\x00\x00\x00/s ? "utf-32be" 169 : /^\x00.\x00/s ? "utf-16be" 170 : /^.\x00\x00\x00/s ? "utf-32le" 171 : /^.\x00.\x00/s ? "utf-16le" 172 : "utf-8"; 173 warn "input text encoding is $enc\n" if $opt_verbose; 174 JSON::XS->new->decode (decode $enc, $_) 175 }, 176 "storable" => sub { Storable::thaw $_ }, 177 "storable-file" => sub { open my $fh, "<", \$_; Storable::fd_retrieve $fh }, 178 "bencode" => sub { require Convert::Bencode; Convert::Bencode::bdecode ($_) }, 179 "clzf" => sub { require Compress::LZF; Compress::LZF::sthaw ($_) }, 180 "yaml" => sub { require YAML; YAML::Load ($_) }, 181 "eval" => sub { my $v = eval "no strict; no warnings; no utf8;\n#line 1 \"input\"\n$_"; die "$@" if $@; $v }, 182); 183 184my %T = ( 185 "none" => sub { "" }, 186 "string" => sub { $_ }, 187 "json" => sub { encode_json $_ }, 188 "json-utf-8" => sub { encode_json $_ }, 189 "json-pretty" => sub { JSON::XS->new->utf8->pretty->encode ($_) }, 190 "json-utf-16le" => sub { encode "utf-16le", JSON::XS->new->encode ($_) }, 191 "json-utf-16be" => sub { encode "utf-16be", JSON::XS->new->encode ($_) }, 192 "json-utf-32le" => sub { encode "utf-32le", JSON::XS->new->encode ($_) }, 193 "json-utf-32be" => sub { encode "utf-32be", JSON::XS->new->encode ($_) }, 194 195 "storable" => sub { Storable::nfreeze $_ }, 196 "storable-file" => sub { open my $fh, ">", \my $buf; Storable::nstore_fd $_, $fh; $buf }, 197 198 "bencode" => sub { require Convert::Bencode; Convert::Bencode::bencode ($_) }, 199 "clzf" => sub { require Compress::LZF; Compress::LZF::sfreeze_cr ($_) }, 200 "yaml" => sub { require YAML; YAML::Dump ($_) }, 201 "dumper" => sub { 202 require Data::Dumper; 203 #local $Data::Dumper::Purity = 1; # hopeless case 204 local $Data::Dumper::Terse = 1; 205 local $Data::Dumper::Indent = 1; 206 local $Data::Dumper::Useqq = 1; 207 local $Data::Dumper::Quotekeys = 0; 208 local $Data::Dumper::Sortkeys = 1; 209 Data::Dumper::Dumper($_) 210 }, 211 "dump" => sub { 212 require Data::Dump; 213 local $Data::Dump::TRY_BASE64 = 0; 214 Data::Dump::dump ($_) . "\n" 215 }, 216); 217 218$F{$opt_from} 219 or die "$opt_from: not a valid fromformat\n"; 220 221$T{$opt_to} 222 or die "$opt_from: not a valid toformat\n"; 223 224if ($opt_from ne "none") { 225 local $/; 226 binmode STDIN; # stupid perl sometimes thinks its funny 227 $_ = <STDIN>; 228} 229 230$_ = $F{$opt_from}->(); 231 232eval $opt_eval; 233die $@ if $@; 234 235$_ = $T{$opt_to}->(); 236 237binmode STDOUT; 238syswrite STDOUT, $_; 239 240 241 242