view release on metacpan or search on metacpan
Added perl2dump_filtered(), perl2dump_homebrew()
and dump_perl_var_recursively().
Fixed scripts to work with new sub names.
0.05 2020-04-16
Makefile.PL minor modification.
0.07 2020-04-20
Changed default options for scripts so that they don't do pretty
printing by default.
Added import parameters 'no-unicode-escape-permanently'
and 'unicode-escape-permanently' for efficient use of *2dump*
subs.
Added benchmarks to time 2dump subs and inserted target in Makefile.
0.08 2020-04-20
Removed dependency to Sub::Override, overriding subs is done by us now.
Fixed POD mistakes.
0.09 2020-04-20
Added dependency Test::Script and Test::Pod (thank you Slaven ReziÄ)
script/json2perl.pl
script/json2yaml.pl
script/perl2json.pl
script/yaml2json.pl
script/yaml2perl.pl
t/00-load.t
t/01-basic.t
t/02-random-data-structure.t
t/03-random-data-structure-UTF8.t
t/04-dump2-use-is-explicit.t
t/05-perl2dump-no-escape-unicode-temporarily.t
t/06-perl2dump-no-escape-unicode-permanently.t
t/07-perl2dump-escape-unicode-permanently.t
t/10-scripts.t
t/11-scripts-pod.t
t/12-from-file.t
t/13-yaml-tricky-cases.t
t/14-yaml-tainted-input.t
t/20-synopsis.t
t/manifest.t
t/pod-coverage.t
t/pod.t
t/t-data/failing/test.json
t/t-data/failing/test.pl
t/t-data/failing/test.yaml
t/t-data/succeeding/test.json
t/t-data/succeeding/test.pl
t/t-data/succeeding/test.yaml
xt/benchmarks/01-default-unicode-escaping.t
xt/benchmarks/02-permanent-no-unicode-escaping.t
xt/benchmarks/03-permanent-unicode-escaping.t
xt/boilerplate.t
xt/deficiencies/01-yaml-quotes-problem.t
xt/deficiencies/02-yaml-pp-remedy.t
xt/deficiencies/03-yaml-xs-remedy.t
META.yml Module YAML meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
{
"abstract" : "convert between Perl data structures, YAML and JSON with unicode support (I believe ...)",
"author" : [
"Andreas Hadjiprocopis <bliako@cpan.org>"
],
"dynamic_config" : 1,
"generated_by" : "ExtUtils::MakeMaker version 7.70, CPAN::Meta::Converter version 2.150010",
"license" : [
"artistic_2"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
---
abstract: 'convert between Perl data structures, YAML and JSON with unicode support (I believe ...)'
author:
- 'Andreas Hadjiprocopis <bliako@cpan.org>'
build_requires:
Benchmark: '0'
Data::Dump: '0'
Data::Dumper: '0'
Data::Random::Structure: '0'
Data::Random::Structure::UTF8: '0.06'
ExtUtils::MakeMaker: '0'
File::Basename: '0'
NAME
Data::Roundtrip - convert between Perl data structures, YAML and JSON
with unicode support (I believe ...)
VERSION
Version 0.30
SYNOPSIS
This module contains a collection of utilities for converting between
JSON, YAML, Perl variable and a Perl variable's string representation
(aka dump). Hopefully, all unicode content will be handled correctly
between the conversions and optionally escaped or un-escaped. Also JSON
can be presented in a pretty format or in a condensed, machine-readable
format (not spaces, indendation or line breaks).
use Data::Roundtrip qw/:all/;
#use Data::Roundtrip qw/json2yaml/;
#use Data::Roundtrip qw/:json/; # see EXPORT
$jsonstr = '{"Songname": "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ",'
.'"Artist": "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ"}'
;
$yamlstr = json2yaml($jsonstr);
print $yamlstr;
# NOTE: long strings have been broken into multilines
# and/or truncated (replaced with ...)
#---
#Artist: ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ
#Songname: ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ
$yamlstr = json2yaml($jsonstr, {'escape-unicode'=>1});
print $yamlstr;
#---
#Artist: \u039a\u03b1\u03b6\u03b1 ...
#Songname: \u0391\u03c0\u03cc\u03ba ...
$backtojson = yaml2json($yamlstr);
# $backtojson is a string representation
# of following JSON structure:
# {"Artist":"ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname":"ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"}
# This is useful when sending JSON via
# a POST request and it needs unicode escaped:
$backtojson = yaml2json($yamlstr, {'escape-unicode'=>1});
# $backtojson is a string representation
# of following JSON structure:
# but this time with unicode escaped
# (pod content truncated for readbility)
# {"Artist":"\u039a\u03b1\u03b6 ...",
# "Songname":"\u0391\u03c0\u03cc ..."}
# this is the usual Data::Dumper dump:
print json2dump($jsonstr);
#$VAR1 = {
# 'Songname' => "\x{391}\x{3c0}\x{3cc} ...",
# 'Artist' => "\x{39a}\x{3b1}\x{3b6} ...",
#};
# and this is a more human-readable version:
print json2dump($jsonstr, {'dont-bloody-escape-unicode'=>1});
# $VAR1 = {
# "Artist" => "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname" => "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"
# };
# pass some parameters to Data::Dumper
# like: be terse (no $VAR1):
print json2dump($jsonstr,
{'dont-bloody-escape-unicode'=>0, 'terse'=>1}
#{'dont-bloody-escape-unicode'=>0, 'terse'=>1, 'indent'=>0}
);
# {
# "Artist" => "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname" => "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"
# }
# this is how to reformat a JSON string to
# have its unicode content escaped:
my $json_with_unicode_escaped =
json2json($jsonstr, {'escape-unicode'=>1});
# With version 0.18 and up two more exported-on-demand
# subs were added to read JSON or YAML directly from a file:
# jsonfile2perl() and yamlfile2perl()
my $perldata = jsonfile2perl("file.json");
my $perldata = yamlfile2perl("file.yaml");
die "failed" unless defined $perldata;
# For some of the above functions there exist command-line scripts:
perl2json.pl -i "perl-data-structure.pl" -o "output.json" --pretty
json2json.pl -i "with-unicode.json" -o "unicode-escaped.json" --escape-unicode
# etc.
# only for *2dump: perl2dump, json2dump, yaml2dump
# and if no escape-unicode is required (i.e.
# setting 'dont-bloody-escape-unicode' => 1 permanently)
# and if efficiency is important,
# meaning that perl2dump is run in a loop thousand of times,
# then import the module like this:
use Data::Roundtrip qw/:all no-unicode-escape-permanently/;
# or like this
use Data::Roundtrip qw/:all unicode-escape-permanently/;
# then perl2dump() is more efficient but unicode characters
# will be permanently not-escaped (1st case) or escaped (2nd case).
EXPORT
By default no symbols are exported. However, the following export tags
are available (:all will export all of them):
* :json : perl2json(), json2perl(), json2dump(), json2yaml(),
json2json(), jsonfile2perl()
* :all : everything above.
* Additionally, these four subs: dump2perl(), dump2json(),
dump2yaml(), dump2dump() do not belong to any export tag. However
they can be imported explicitly by the caller in the usual way (e.g.
use Data::Roundtrip qw/dump2perl perl2json .../). Section CAVEATS,
under "dump2perl", describes how these subs eval() a string possibly
coming from user, possibly being unchecked.
* no-unicode-escape-permanently : this is not an export
keyword/parameter but a parameter which affects all the *2dump* subs
by setting unicode escaping permanently to false. See "EFFICIENCY".
* unicode-escape-permanently : this is not an export
keyword/parameter but a parameter which affects all the *2dump* subs
by setting unicode escaping permanently to true. See "EFFICIENCY".
EFFICIENCY
The export keyword/parameter no-unicode-escape-permanently affects all
the *2dump* subs by setting unicode escaping permanently to false. This
improves efficiency, although one will ever need to use this in extreme
situations where a *2dump* sub is called repeatedly in a loop of a few
hundreds or thousands of iterations or more.
Each time a *2dump* is called, the dont-bloody-escape-unicode flag is
checked and if it is set, then Data::Dumper's qquote() is overriden
with _qquote_redefinition_by_Corion() just for that instance and will
be restored as soon as the dump is finished. Similarly, a filter for
not escaping unicode is added to Data::Dump just for that particular
call and is removed immediately after. This has some computational cost
and can be avoided completely by overriding the sub and adding the
filter once, at loading (in import()).
The price to pay for this added efficiency is that unicode in any dump
will never be escaped (e.g. \x{3b1}), but will be rendered (e.g. α, a
greek alpha). Always. The option dont-bloody-escape-unicode will
permanently be set to true.
Similarly, the export keyword/parameter unicode-escape-permanently
affects all the *2dump* subs by setting unicode escaping permanently to
true. This improves efficiency as well.
See "BENCHMARKS" on how to find the fastest *2dump* sub.
BENCHMARKS
The special Makefile target benchmarks will time calls to each of the
*2dump* subs under
use Data::Roundtrip;
use Data::Roundtrip qw/no-unicode-escape-permanently/;
use Data::Roundtrip qw/unicode-escape-permanently/;
and for 'dont-bloody-escape-unicode' => 0 and
'dont-bloody-escape-unicode' => 1.
In general, "perl2dump" is faster by 25% when one of the permanent
import parameters is used (either of the last two cases above).
SUBROUTINES
perl2json
my $ret = perl2json($perlvar, $optional_paramshashref)
* $optional_paramshashref
Return value:
* $ret
Given an input $perlvar (which can be a simple scalar or a nested data
structure, but not an object), it will return the equivalent JSON
string. In $optional_paramshashref one can specify whether to escape
unicode with 'escape-unicode' => 1 and/or prettify the returned result
with 'pretty' => 1 and/or allow conversion of blessed objects with
'convert_blessed' => 1.
The latter is useful when the input (Perl) data structure contains Perl
objects (blessed refs!). But in addition to setting it, each of the
Perl objects (their class) must implement a TO_JSON() method which will
simply convert the object into a Perl data structure. For example, if
your object stores the important data in $self->data as a hash, then
use this to return it
* $optional_paramshashref
Return value:
* $ret
Given an input $perlvar (which can be a simple scalar or a nested data
structure, but not an object), it will return the equivalent YAML
string. In $optional_paramshashref one can specify whether to escape
unicode with 'escape-unicode' => 1. Prettify is not supported yet. The
output can be fed to "yaml2perl" for getting the Perl variable back.
It returns the YAML string on success or undef on failure.
yaml2perl
my $ret = yaml2perl($yamlstring);
Arguments:
* $optional_paramshashref
Return value:
* $ret
Given an input $perlvar (which can be a simple scalar or a nested data
structure, but not an object), it will return the equivalent string
(via Data::Dumper). In $optional_paramshashref one can specify whether
to escape unicode with 'dont-bloody-escape-unicode' => 0, (or
'escape-unicode' => 1). The DEFAULT behaviour is to NOT ESCAPE unicode.
Additionally, use terse output with 'terse' => 1 and remove all the
incessant indentation with 'indent' => 1 which unfortunately goes to
the other extreme of producing a space-less output, not fit for human
consumption. The output can be fed to "dump2perl" for getting the Perl
variable back.
It returns the string representation of the input perl variable on
success or undef on failure.
The output can be fed back to "dump2perl".
CAVEAT: when not escaping unicode (which is the default behaviour),
each call to this sub will override Data::Dumper's qquote() sub then
call Data::Dumper's Dumper() and save its output to a temporary
variable, restore qquote() sub to its original code ref and return the
contents. This exercise is done every time this perl2dump() is called.
It may be expensive. The alternative is to redefine qquote() once, when
the module is loaded, with all the side-effects this may cause.
Note that there are two other alternative subs which offer more-or-less
the same functionality and their output can be fed back to all the
dump2*() subs. These are "perl2dump_filtered" which uses
Data::Dump::Filtered to add a filter to control unicode escaping but
lacks in aesthetics and functionality and handling all the cases Dump
and Dumper do quite well.
There is also perl2dump_homebrew() which uses the same dump-recursively
engine as "perl2dump_filtered" but does not involve Data::Dump at all.
perl2dump_filtered
my $ret = perl2dump_filtered($perlvar, $optional_paramshashref)
* $perl_var, a Perl variable like a scalar or an arbitrarily nested
data structure. For the latter, it requires references, e.g. hash-ref
or arrayref.
Return value:
* $ret, the stringified version of the input Perl variable.
This sub will take a Perl var (as a scalar or an arbitrarily nested
data structure) and emulate a very very basic Dump/Dumper but with
enforced rendering unicode (for keys or values or array items), and not
escaping unicode - this is not an option, it returns a string
representation of the input perl var
There are 2 obvious limitations:
1. indentation is very basic,
2. it supports only scalars, hashes and arrays, (which will dive into
them no problem) This sub can be used in conjuction with
DataDumpFilterino() to create a Data::Dump filter like,
Given an input YAML string $yamlstring, it will return the equivalent
YAML string YAML by first converting YAML to a Perl variable and then
converting that variable to JSON using "perl2json". All the parameters
supported by "perl2json" are accepted.
It returns the JSON string on success or undef on failure.
json2json yaml2yaml
Transform a json or yaml string via pretty printing or via escaping
unicode or via un-escaping unicode. Parameters like above will be
accepted.
json2dump dump2json yaml2dump dump2yaml
These subs offer similar functionality as their counterparts described
above.
Section CAVEATS, under "dump2perl", describes how dump2*() subs eval()
a string possibly coming from user, possibly being unchecked.
Return value:
* $ret
For example:
my $dumpstr = '...';
my $newdumpstr = dump2dump(
$dumpstr,
{
'dont-bloody-escape-unicode' => 1,
'terse' => 0,
}
);
It returns the a dump string similar to
read_from_file
my $contents = read_from_file($filename)
BUGS
Please report any bugs or feature requests to bug-data-roundtrip at
rt.cpan.org, or through the web interface at
https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Roundtrip. I will
be notified, and then you'll automatically be notified of progress on
your bug as I make changes.
SEE ALSO
Convert JSON to Perl and back with unicode
<https://perlmonks.org/?node_id=11115241>
RFC: Perl<->JSON<->YAML<->Dumper : roundtripping and possibly with
unicode <https://perlmonks.org/?node_id=11115280>
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Data::Roundtrip
You can also look for information at:
* RT: CPAN's request tracker (report bugs here)
https://metacpan.org/release/Data-Roundtrip
ACKNOWLEDGEMENTS
Several Monks at PerlMonks.org (in no particular order):
haukex <https://perlmonks.org/?node_id=830549>
Corion <https://perlmonks.org/?node_id=5348> (the
_qquote_redefinition_by_Corion() which harnesses Data::Dumper's
incessant unicode escaping)
kcott <https://perlmonks.org/?node_id=861371> (The EXPORT section among
other suggestions)
jwkrahn <https://perlmonks.org/?node_id=540414>
leszekdubiel <https://perlmonks.org/?node_id=1164259>
marto <https://perlmonks.org/?node_id=324763>
# NAME
Data::Roundtrip - convert between Perl data structures, YAML and JSON with unicode support (I believe ...)
# VERSION
Version 0.30
# SYNOPSIS
This module contains a collection of utilities for converting between
JSON, YAML, Perl variable and a Perl variable's string representation (aka dump).
Hopefully, all unicode content will be handled correctly between
the conversions and optionally escaped or un-escaped. Also JSON can
be presented in a pretty format or in a condensed, machine-readable
format (not spaces, indendation or line breaks).
use Data::Roundtrip qw/:all/;
#use Data::Roundtrip qw/json2yaml/;
#use Data::Roundtrip qw/:json/; # see EXPORT
$jsonstr = '{"Songname": "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ",'
.'"Artist": "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ"}'
;
$yamlstr = json2yaml($jsonstr);
print $yamlstr;
# NOTE: long strings have been broken into multilines
# and/or truncated (replaced with ...)
#---
#Artist: ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ
#Songname: ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ
$yamlstr = json2yaml($jsonstr, {'escape-unicode'=>1});
print $yamlstr;
#---
#Artist: \u039a\u03b1\u03b6\u03b1 ...
#Songname: \u0391\u03c0\u03cc\u03ba ...
$backtojson = yaml2json($yamlstr);
# $backtojson is a string representation
# of following JSON structure:
# {"Artist":"ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname":"ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"}
# This is useful when sending JSON via
# a POST request and it needs unicode escaped:
$backtojson = yaml2json($yamlstr, {'escape-unicode'=>1});
# $backtojson is a string representation
# of following JSON structure:
# but this time with unicode escaped
# (pod content truncated for readbility)
# {"Artist":"\u039a\u03b1\u03b6 ...",
# "Songname":"\u0391\u03c0\u03cc ..."}
# this is the usual Data::Dumper dump:
print json2dump($jsonstr);
#$VAR1 = {
# 'Songname' => "\x{391}\x{3c0}\x{3cc} ...",
# 'Artist' => "\x{39a}\x{3b1}\x{3b6} ...",
#};
# and this is a more human-readable version:
print json2dump($jsonstr, {'dont-bloody-escape-unicode'=>1});
# $VAR1 = {
# "Artist" => "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname" => "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"
# };
# pass some parameters to Data::Dumper
# like: be terse (no $VAR1):
print json2dump($jsonstr,
{'dont-bloody-escape-unicode'=>0, 'terse'=>1}
#{'dont-bloody-escape-unicode'=>0, 'terse'=>1, 'indent'=>0}
);
# {
# "Artist" => "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname" => "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"
# }
# this is how to reformat a JSON string to
# have its unicode content escaped:
my $json_with_unicode_escaped =
json2json($jsonstr, {'escape-unicode'=>1});
# With version 0.18 and up two more exported-on-demand
# subs were added to read JSON or YAML directly from a file:
# jsonfile2perl() and yamlfile2perl()
my $perldata = jsonfile2perl("file.json");
my $perldata = yamlfile2perl("file.yaml");
die "failed" unless defined $perldata;
# For some of the above functions there exist command-line scripts:
perl2json.pl -i "perl-data-structure.pl" -o "output.json" --pretty
json2json.pl -i "with-unicode.json" -o "unicode-escaped.json" --escape-unicode
# etc.
# only for *2dump: perl2dump, json2dump, yaml2dump
# and if no escape-unicode is required (i.e.
# setting 'dont-bloody-escape-unicode' => 1 permanently)
# and if efficiency is important,
# meaning that perl2dump is run in a loop thousand of times,
# then import the module like this:
use Data::Roundtrip qw/:all no-unicode-escape-permanently/;
# or like this
use Data::Roundtrip qw/:all unicode-escape-permanently/;
# then perl2dump() is more efficient but unicode characters
# will be permanently not-escaped (1st case) or escaped (2nd case).
# EXPORT
By default no symbols are exported. However, the following export tags are available (:all will export all of them):
- `:json` :
`perl2json()`,
`json2perl()`,
`json2dump()`,
- `:io` :
`read_from_file()`, `write_to_file()`,
`read_from_filehandle()`, `write_to_filehandle()`,
- `:all` : everything above.
- Additionally, these four subs: `dump2perl()`, `dump2json()`, `dump2yaml()`, `dump2dump()`
do not belong to any export tag. However they can be imported explicitly by the caller
in the usual way (e.g. `use Data::Roundtrip qw/dump2perl perl2json .../`).
Section CAVEATS, under ["dump2perl"](#dump2perl), describes how these
subs `eval()` a string possibly coming from user,
possibly being unchecked.
- `no-unicode-escape-permanently` : this is not an
export keyword/parameter but a parameter which affects
all the `*2dump*` subs by setting unicode escaping
permanently to false. See ["EFFICIENCY"](#efficiency).
- `unicode-escape-permanently` : this is not an
export keyword/parameter but a parameter which affects
all the `*2dump*` subs by setting unicode escaping
permanently to true. See ["EFFICIENCY"](#efficiency).
# EFFICIENCY
The export keyword/parameter `no-unicode-escape-permanently`
affects
all the `*2dump*` subs by setting unicode escaping
permanently to false. This improves efficiency, although
one will ever need to
use this in extreme situations where a `*2dump*`
sub is called repeatedly in a loop of
a few hundreds or thousands of iterations or more.
Each time a `*2dump*` is called, the
`dont-bloody-escape-unicode` flag is checked
and if it is set, then [Data::Dumper](https://metacpan.org/pod/Data%3A%3ADumper)'s `qquote()`
is overriden with `_qquote_redefinition_by_Corion()`
just for that instance and will be restored as soon as
the dump is finished. Similarly, a filter for
not escaping unicode is added to [Data::Dump](https://metacpan.org/pod/Data%3A%3ADump)
just for that particular call and is removed immediately
after. This has some computational cost and can be
avoided completely by overriding the sub
and adding the filter once, at loading (in `import()`).
The price to pay for this added efficiency is that
unicode in any dump will never be escaped (e.g. `\x{3b1})`,
but will be rendered (e.g. `α`, a greek alpha). Always.
The option
`dont-bloody-escape-unicode` will permanently be set to true.
Similarly, the export keyword/parameter
`unicode-escape-permanently`
affects
all the `*2dump*` subs by setting unicode escaping
permanently to true. This improves efficiency as well.
See ["BENCHMARKS"](#benchmarks) on how to find the fastest `*2dump*`
sub.
# BENCHMARKS
The special Makefile target `benchmarks` will time
calls to each of the `*2dump*` subs under
use Data::Roundtrip;
use Data::Roundtrip qw/no-unicode-escape-permanently/;
use Data::Roundtrip qw/unicode-escape-permanently/;
and for `'dont-bloody-escape-unicode' => 0` and
`'dont-bloody-escape-unicode' => 1`.
In general, ["perl2dump"](#perl2dump) is faster by 25% when one of the
permanent import parameters is used
(either of the last two cases above).
# SUBROUTINES
## `perl2json`
my $ret = perl2json($perlvar, $optional_paramshashref)
- `$perlvar`
- `$optional_paramshashref`
Return value:
- `$ret`
Given an input `$perlvar` (which can be a simple scalar or
a nested data structure, but not an object), it will return
the equivalent JSON string. In `$optional_paramshashref`
one can specify whether to escape unicode with
`'escape-unicode' => 1`
and/or prettify the returned result with `'pretty' => 1`
and/or allow conversion of blessed objects with `'convert_blessed' => 1`.
The latter is useful when the input (Perl) data structure
contains Perl objects (blessed refs!). But in addition to
setting it, each of the Perl objects (their class) must
implement a `TO_JSON()` method which will simply convert
the object into a Perl data structure. For example, if
your object stores the important data in `$self->data`
as a hash, then use this to return it
- `$perlvar`
- `$optional_paramshashref`
Return value:
- `$ret`
Given an input `$perlvar` (which can be a simple scalar or
a nested data structure, but not an object), it will return
the equivalent YAML string. In `$optional_paramshashref`
one can specify whether to escape unicode with
`'escape-unicode' => 1`. Prettify is not supported yet.
The output can be fed to ["yaml2perl"](#yaml2perl)
for getting the Perl variable back.
It returns the YAML string on success or `undef` on failure.
## `yaml2perl`
my $ret = yaml2perl($yamlstring);
Arguments:
- `$optional_paramshashref`
Return value:
- `$ret`
Given an input `$perlvar` (which can be a simple scalar or
a nested data structure, but not an object), it will return
the equivalent string (via [Data::Dumper](https://metacpan.org/pod/Data%3A%3ADumper)).
In `$optional_paramshashref`
one can specify whether to escape unicode with
`'dont-bloody-escape-unicode' => 0`,
(or `'escape-unicode' => 1`). The DEFAULT
behaviour is to NOT ESCAPE unicode.
Additionally, use terse output with `'terse' => 1` and remove
all the incessant indentation with `'indent' => 1`
which unfortunately goes to the other extreme of
producing a space-less output, not fit for human consumption.
The output can be fed to ["dump2perl"](#dump2perl)
for getting the Perl variable back.
It returns the string representation of the input perl variable
on success or `undef` on failure.
The output can be fed back to ["dump2perl"](#dump2perl).
CAVEAT: when not escaping unicode (which is the default
behaviour), each call to this sub will override [Data::Dumper](https://metacpan.org/pod/Data%3A%3ADumper)'s
`qquote()` sub then
call [Data::Dumper](https://metacpan.org/pod/Data%3A%3ADumper)'s `Dumper()` and save its output to
a temporary variable, restore `qquote()` sub to its original
code ref and return the
contents. This exercise is done every time this `perl2dump()`
is called. It may be expensive. The alternative is
to redefine `qquote()` once, when the module is loaded, with
all the side-effects this may cause.
Note that there are two other alternative subs which offer more-or-less
the same functionality and their output can be fed back to all the `dump2*()`
subs. These are
["perl2dump\_filtered"](#perl2dump_filtered) which uses [Data::Dump::Filtered](https://metacpan.org/pod/Data%3A%3ADump%3A%3AFiltered)
to add a filter to control unicode escaping but
lacks in aesthetics and functionality and handling all the
cases Dump and Dumper do quite well.
There is also `perl2dump_homebrew()` which
uses the same dump-recursively engine as
["perl2dump\_filtered"](#perl2dump_filtered)
but does not involve Data::Dump at all.
## `perl2dump_filtered`
a scalar or an arbitrarily nested data structure.
For the latter, it requires references, e.g.
hash-ref or arrayref.
Return value:
- `$ret`, the stringified version of the input Perl variable.
This sub will take a Perl var (as a scalar or an arbitrarily nested data structure)
and emulate a very very basic
Dump/Dumper but with enforced rendering unicode (for keys or values or array items),
and not escaping unicode - this is not an option,
it returns a string representation of the input perl var
There are 2 obvious limitations:
- 1. indentation is very basic,
- 2. it supports only scalars, hashes and arrays,
(which will dive into them no problem)
This sub can be used in conjuction with DataDumpFilterino()
to create a Data::Dump filter like,
by first converting YAML to a Perl variable and then
converting that variable to JSON using ["perl2json"](#perl2json).
All the parameters supported by ["perl2json"](#perl2json)
are accepted.
It returns the JSON string on success or `undef` on failure.
## `json2json` `yaml2yaml`
Transform a json or yaml string via pretty printing or via
escaping unicode or via un-escaping unicode. Parameters
like above will be accepted.
## `json2dump` `dump2json` `yaml2dump` `dump2yaml`
These subs offer similar functionality as their counterparts
described above.
Section CAVEATS, under ["dump2perl"](#dump2perl), describes how
`dump2*()` subs `eval()` a string possibly coming from user,
possibly being unchecked.
Return value:
- `$ret`
For example:
my $dumpstr = '...';
my $newdumpstr = dump2dump(
$dumpstr,
{
'dont-bloody-escape-unicode' => 1,
'terse' => 0,
}
);
It returns the a dump string similar to
## `read_from_file`
my $contents = read_from_file($filename)
Andreas Hadjiprocopis, `<bliako at cpan.org> / <andreashad2 at gmail.com>`
# BUGS
Please report any bugs or feature requests to `bug-data-roundtrip at rt.cpan.org`, or through
the web interface at [https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Roundtrip](https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Roundtrip). I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
# SEE ALSO
- [Convert JSON to Perl and back with unicode](https://perlmonks.org/?node_id=11115241)
- [RFC: Perl<->JSON<->YAML<->Dumper : roundtripping and possibly with unicode](https://perlmonks.org/?node_id=11115280)
# SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Data::Roundtrip
You can also look for information at:
- RT: CPAN's request tracker (report bugs here)
[https://metacpan.org/release/Data-Roundtrip](https://metacpan.org/release/Data-Roundtrip)
# ACKNOWLEDGEMENTS
Several Monks at [PerlMonks.org ](https://metacpan.org/pod/%20https%3A#PerlMonks.org) (in no particular order):
- [haukex](https://perlmonks.org/?node_id=830549)
- [Corion](https://perlmonks.org/?node_id=5348) (the
`_qquote_redefinition_by_Corion()` which harnesses
[Data::Dumper](https://metacpan.org/pod/Data%3A%3ADumper)'s incessant unicode escaping)
- [kcott](https://perlmonks.org/?node_id=861371)
(The EXPORT section among other suggestions)
- [jwkrahn](https://perlmonks.org/?node_id=540414)
- [leszekdubiel](https://perlmonks.org/?node_id=1164259)
- [marto](https://perlmonks.org/?node_id=324763)
- [Haarg](https://perlmonks.org/?node_id=306692)
- and an anonymous monk
- CPAN author Slaven ReziÄ
([SREZIC](https://metacpan.org/author/SREZIC)) for testing
the code and reporting numerous problems.
lib/Data/Roundtrip.pm view on Meta::CPAN
package Data::Roundtrip;
use 5.008;
use strict;
use warnings;
our $VERSION = '0.30';
# import params is just one 'no-unicode-escape-permanently'
# if set, then unicode escaping will not happen at
# all, even if 'dont-bloody-escape-unicode' is set.
# Dump's filter and Dumper's qquote overwrite will be permanent
# which is more efficient but removes the flexibility
# of having unicode escaped and rendered at will.
use Encode qw/encode_utf8 decode_utf8/;
use JSON qw/decode_json encode_json/;
use Unicode::Escape qw/escape unescape/;
# YAML v1.30 fails for {"\"aaa'bbb" => "aaa","bbb" => 1,}
# while YAML::PP and YAML::XS both succeed
# YAML::PP is less restrictive so using this
# YAML v1.31 now behaves correctly, run 'make deficiencies' to see that
# but since YAML author urges not use this module, we will
# be using YAML::PP
lib/Data/Roundtrip.pm view on Meta::CPAN
sub DESTROY {
Data::Dump::Filtered::remove_dump_filter( \& DataDumpFilterino )
if $_permanent_filter;
}
sub import {
# what comes here is (package, param1, param2...) = @_
# for something like
# use Data::Roundtrip qw/param1 params2 .../;
# we are looking for a param, eq to 'no-unicode-escape-permanently'
# or 'unicode-escape-permanently'
# the rest we must pass to the Exporter::import() but in a tricky way
# so as it injects all these subs in the proper namespace.
# that call is at the end, but with our parameter removed from the list
for(my $i=@_;$i-->1;){
if( $_[$i] eq 'no-unicode-escape-permanently' ){
splice @_, $i, 1; # remove it from the list
$Data::Dumper::Useperl = 1;
$Data::Dumper::Useqq='utf8';
no warnings 'redefine';
*Data::Dumper::qquote = \& _qquote_redefinition_by_Corion;
$_permanent_override = 1;
# add a filter to Data::Dump
Data::Dump::Filtered::add_dump_filter( \& DataDumpFilterino );
$_permanent_filter = 1;
} elsif( $_[$i] eq 'unicode-escape-permanently' ){
splice @_, $i, 1; # remove it from the list
# this is the case which we want to escape unicode permanently
# which is the default behaviour for Dump and Dumper
$_permanent_override = 2;
$_permanent_filter = 2;
}
}
# now let Exporter handle the rest of the params if any
# from ikegami at https://www.perlmonks.org/?node_id=1214104
goto &Exporter::import;
}
sub perl2json {
my $pv = $_[0];
my $params = defined($_[1]) ? $_[1] : {};
my $pretty_printing = exists($params->{'pretty'}) && defined($params->{'pretty'})
? $params->{'pretty'} : 0
;
my $escape_unicode = exists($params->{'escape-unicode'}) && defined($params->{'escape-unicode'})
? $params->{'escape-unicode'} : 0
;
my $convert_blessed = exists($params->{'convert_blessed'}) && defined($params->{'convert_blessed'})
? $params->{'convert_blessed'} : 0
;
my $json_string;
# below we check $json_string after each time it is set because of eval{} and
# don't want to loose $@
my $encoder = JSON->new;
$encoder = $encoder->pretty if $pretty_printing;
# convert_blessed will allow when finding objects to
# ask them if they have a TO_JSON method which returns
# the object as a perl data structure which is then converted
# to JSON.
# for example if your object stores the important data you
# want to print in $self->{'data'}
# then sub TO_JSON { shift->{'data'} }
# see https://perldoc.perl.org/JSON::PP#2.-convert_blessed-is-enabled-and-the-object-has-a-TO_JSON-method.
$encoder = $encoder->convert_blessed if $convert_blessed;
if( $escape_unicode ){
$json_string = eval { $encoder->utf8(1)->encode($pv) };
if( ! defined($json_string) ){ print STDERR "error, call to ".'JSON->new->utf8(1)->encode()'." has failed".((defined($@)&&($@!~/^\s*$/))?" with this exception:\n".$@:".")."\n"; return undef }
if ( _has_utf8($json_string) ){
$json_string = Unicode::Escape::escape($json_string, 'utf8');
if( ! defined($json_string) ){ print STDERR "error, call to ".'Unicode::Escape::escape()'." has failed.\n"; return undef }
}
} else {
$json_string = eval { $encoder->utf8(0)->encode($pv) };
if( ! defined($json_string) ){ print STDERR "error, call to ".'JSON->new->utf8(0)->pretty->encode()'." has failed".((defined($@)&&($@!~/^\s*$/))?" with this exception:\n".$@:".")."\n"; return undef }
}
lib/Data/Roundtrip.pm view on Meta::CPAN
}
sub perl2yaml {
my $pv = $_[0];
my $params = defined($_[1]) ? $_[1] : {};
my $pretty_printing = exists($params->{'pretty'}) && defined($params->{'pretty'})
? $params->{'pretty'} : 0
;
print STDERR "perl2yaml() : pretty-printing is not supported for YAML output\n" and $pretty_printing=0
if $pretty_printing;
my $escape_unicode = exists($params->{'escape-unicode'}) && defined($params->{'escape-unicode'})
? $params->{'escape-unicode'} : 0
;
my ($yaml_string, $escaped);
if( $escape_unicode ){
#if( $pretty_printing ){
# it's here just for historic purposes, this is not supported and a warning is issued
#$yaml_string = eval { YAML::PP::Dump($pv) };
#if( ! defined $yaml_string ){ print STDERR "error, call to ".'YAML::PP::Dump()'." has failed with this exception:\n".$@."\n"; return undef }
# this does not work :( no pretty printing for yaml
#$yaml_string = Data::Format::Pretty::YAML::format_pretty($pv);
#} else {
# intercepting a die by wrapping in an eval
$yaml_string = eval { YAML::PP::Dump($pv) };
if( ! defined($yaml_string) ){ print STDERR "error, call to ".'YAML::PP::Dump()'." has failed".((defined($@)&&($@!~/^\s*$/))?" with this exception:\n".$@:".")."\n"; return undef }
lib/Data/Roundtrip.pm view on Meta::CPAN
if( ! defined($pv) ){ print STDERR "input string:${dump_string}\nend input string.\ndump2perl() : error, eval() of input string (alledgedly a perl variable, see above) has failed".((defined($@)&&($@!~/^\s*$/))?" with this exception:\n".$@:".")."\n";...
return $pv
}
# this bypasses Data::Dumper's obsession with escaping
# non-ascii characters by redefining the qquote() sub
# The redefinition code is by [Corion] @ Perlmonks and cpan
# see https://perlmonks.org/?node_id=11115271
# So, it still uses Data::Dumper to dump the input perl var
# but with its qquote() sub redefined. See section CAVEATS
# for a wee problem that may appear in the future.
# The default behaviour is NOT to escape unicode
# (which is the opposite of what Data::Dumper is doing)
# see options, below, on how to change this.
# input is the perl variable (as a reference, e.g. scalar, hashref, arrayref)
# followed by optional hashref of options which can be
# terse
# indent
# dont-bloody-escape-unicode,
# escape-unicode,
# The last 2 control how unicode is printed, either escaped,
# like \x{3b1} or 'a' <<< which is unicoded greek alpha but did not want to pollute with unicode this file
# the former behaviour can be with dont-bloody-escape-unicode=>0 or escape-unicode=>1,
# the latter behaviour is the default. but setting the opposite of above will set it.
# NOTE: there are 2 alternatives to this
# perl2dump_filtered() which uses Data::Dump filters to control unicode escaping but
# lacks in aesthetics and functionality and handling all the cases Dump and Dumper
# do quite well.
# perl2dump_homebrew() uses the same dump-recursively engine but does not involve
# Data::Dump at all.
sub perl2dump {
my $pv = $_[0];
my $params = defined($_[1]) ? $_[1] : {};
local $Data::Dumper::Terse = exists($params->{'terse'}) && defined($params->{'terse'})
? $params->{'terse'} : 0
;
local $Data::Dumper::Indent = exists($params->{'indent'}) && defined($params->{'indent'})
? $params->{'indent'} : 1
;
if( ($_permanent_override == 0)
&& ((
exists($params->{'dont-bloody-escape-unicode'}) && defined($params->{'dont-bloody-escape-unicode'})
&& ($params->{'dont-bloody-escape-unicode'}==1)
) || (
exists($params->{'escape-unicode'}) && defined($params->{'escape-unicode'})
&& ($params->{'escape-unicode'}==0)
)
)
){
# this is the case where no 'no-unicode-escape-permanently'
# was used at loading the module
# we have to use the special qquote each time caller
# sets 'dont-bloody-escape-unicode'=>1
# which will be replaced with the original sub
# once we exit this scope.
# make benchmarks will compare all cases if you ever
# want to get more efficiency out of this
local $Data::Dumper::Useperl = 1;
local $Data::Dumper::Useqq='utf8';
no warnings 'redefine';
local *Data::Dumper::qquote = \& _qquote_redefinition_by_Corion;
return Data::Dumper::Dumper($pv);
# out of scope local's will be restored to original values
lib/Data/Roundtrip.pm view on Meta::CPAN
}
# This uses Data::Dump's filters
# The _qquote_redefinition_by_Corion() code is by [Corion] @ Perlmonks and cpan
# see https://perlmonks.org/?node_id=11115271
sub perl2dump_filtered {
my $pv = $_[0];
my $params = defined($_[1]) ? $_[1] : {};
if( ($_permanent_filter == 0)
&& ((
exists($params->{'dont-bloody-escape-unicode'}) && defined($params->{'dont-bloody-escape-unicode'})
&& ($params->{'dont-bloody-escape-unicode'}==1)
) || (
exists($params->{'escape-unicode'}) && defined($params->{'escape-unicode'})
&& ($params->{'escape-unicode'}==0)
)
)
){
Data::Dump::Filtered::add_dump_filter( \& DataDumpFilterino );
my $ret = Data::Dump::pp($pv);
Data::Dump::Filtered::remove_dump_filter( \& DataDumpFilterino );
return $ret;
}
return Data::Dump::pp($pv);
}
sub perl2dump_homebrew {
my $pv = $_[0];
my $params = defined($_[1]) ? $_[1] : {};
if( ($_permanent_override == 1)
|| (
exists($params->{'dont-bloody-escape-unicode'}) && defined($params->{'dont-bloody-escape-unicode'})
&& ($params->{'dont-bloody-escape-unicode'}==1)
) || (
exists($params->{'escape-unicode'}) && defined($params->{'escape-unicode'})
&& ($params->{'escape-unicode'}==0)
)
){
return dump_perl_var_recursively($pv);
}
return Data::Dumper::Dumper($pv);
}
# this will take a perl var (as a scalar or an arbitrarily nested data structure)
# and emulate a very very basic
# Dump/Dumper but with rendering unicode (for keys or values or array items)
# it returns a string representation of the input perl var
# There are 2 obvious limitations:
# 1) indentation is very basic,
# 2) it supports only scalars, hashes and arrays,
# (which will dive into them no problem)
# This sub can be used in conjuction with DataDumpFilterino()
# to create a Data::Dump filter like,
# Data::Dump::Filtered::add_dump_filter( \& DataDumpFilterino );
# or dumpf($perl_var, \& DataDumpFilterino);
# the input is a perl-var as a reference, so no %inp but $inp={} or $inp=[]
lib/Data/Roundtrip.pm view on Meta::CPAN
s/($Data_Dumper_low_controls)/'\\'.sprintf('%03o',ord($1))/eg;
# all but last branch below not supported --BEHAVIOR SUBJECT TO CHANGE--
my $high = shift || "";
if ($high eq "iso8859") { # Doesn't escape the Latin1 printables
if ($Data_Dumper_IS_ASCII) {
s/([\200-\240])/'\\'.sprintf('%o',ord($1))/eg;
}
elsif ($] ge 5.007_003) {
my $high_control = utf8::unicode_to_native(0x9F);
s/$high_control/sprintf('\\%o',ord($1))/eg;
}
} elsif ($high eq "utf8") {
# Some discussion of what to do here is in
# https://rt.perl.org/Ticket/Display.html?id=113088
# use utf8;
# $str =~ s/([^\040-\176])/sprintf "\\x{%04x}", ord($1)/ge;
} elsif ($high eq "8bit") {
# leave it as it is
} else {
lib/Data/Roundtrip.pm view on Meta::CPAN
}
return qq("$_");
}
# begin pod
=pod
=encoding utf8
=head1 NAME
Data::Roundtrip - convert between Perl data structures, YAML and JSON with unicode support (I believe ...)
=head1 VERSION
Version 0.30
=head1 SYNOPSIS
This module contains a collection of utilities for converting between
JSON, YAML, Perl variable and a Perl variable's string representation (aka dump).
Hopefully, all unicode content will be handled correctly between
the conversions and optionally escaped or un-escaped. Also JSON can
be presented in a pretty format or in a condensed, machine-readable
format (not spaces, indendation or line breaks).
use Data::Roundtrip qw/:all/;
#use Data::Roundtrip qw/json2yaml/;
#use Data::Roundtrip qw/:json/; # see EXPORT
$jsonstr = '{"Songname": "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ",'
.'"Artist": "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ"}'
;
$yamlstr = json2yaml($jsonstr);
print $yamlstr;
# NOTE: long strings have been broken into multilines
# and/or truncated (replaced with ...)
#---
#Artist: ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ
#Songname: ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ
$yamlstr = json2yaml($jsonstr, {'escape-unicode'=>1});
print $yamlstr;
#---
#Artist: \u039a\u03b1\u03b6\u03b1 ...
#Songname: \u0391\u03c0\u03cc\u03ba ...
$backtojson = yaml2json($yamlstr);
# $backtojson is a string representation
# of following JSON structure:
# {"Artist":"ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname":"ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"}
# This is useful when sending JSON via
# a POST request and it needs unicode escaped:
$backtojson = yaml2json($yamlstr, {'escape-unicode'=>1});
# $backtojson is a string representation
# of following JSON structure:
# but this time with unicode escaped
# (pod content truncated for readbility)
# {"Artist":"\u039a\u03b1\u03b6 ...",
# "Songname":"\u0391\u03c0\u03cc ..."}
# this is the usual Data::Dumper dump:
print json2dump($jsonstr);
#$VAR1 = {
# 'Songname' => "\x{391}\x{3c0}\x{3cc} ...",
# 'Artist' => "\x{39a}\x{3b1}\x{3b6} ...",
#};
# and this is a more human-readable version:
print json2dump($jsonstr, {'dont-bloody-escape-unicode'=>1});
# $VAR1 = {
# "Artist" => "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname" => "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"
# };
# pass some parameters to Data::Dumper
# like: be terse (no $VAR1):
print json2dump($jsonstr,
{'dont-bloody-escape-unicode'=>0, 'terse'=>1}
#{'dont-bloody-escape-unicode'=>0, 'terse'=>1, 'indent'=>0}
);
# {
# "Artist" => "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ",
# "Songname" => "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ"
# }
# this is how to reformat a JSON string to
# have its unicode content escaped:
my $json_with_unicode_escaped =
json2json($jsonstr, {'escape-unicode'=>1});
# With version 0.18 and up two more exported-on-demand
# subs were added to read JSON or YAML directly from a file:
# jsonfile2perl() and yamlfile2perl()
my $perldata = jsonfile2perl("file.json");
my $perldata = yamlfile2perl("file.yaml");
die "failed" unless defined $perldata;
# For some of the above functions there exist command-line scripts:
perl2json.pl -i "perl-data-structure.pl" -o "output.json" --pretty
json2json.pl -i "with-unicode.json" -o "unicode-escaped.json" --escape-unicode
# etc.
# only for *2dump: perl2dump, json2dump, yaml2dump
# and if no escape-unicode is required (i.e.
# setting 'dont-bloody-escape-unicode' => 1 permanently)
# and if efficiency is important,
# meaning that perl2dump is run in a loop thousand of times,
# then import the module like this:
use Data::Roundtrip qw/:all no-unicode-escape-permanently/;
# or like this
use Data::Roundtrip qw/:all unicode-escape-permanently/;
# then perl2dump() is more efficient but unicode characters
# will be permanently not-escaped (1st case) or escaped (2nd case).
=head1 EXPORT
By default no symbols are exported. However, the following export tags are available (:all will export all of them):
=over 4
=item * C<:json> :
C<perl2json()>,
lib/Data/Roundtrip.pm view on Meta::CPAN
=item * C<:all> : everything above.
=item * Additionally, these four subs: C<dump2perl()>, C<dump2json()>, C<dump2yaml()>, C<dump2dump()>
do not belong to any export tag. However they can be imported explicitly by the caller
in the usual way (e.g. C<use Data::Roundtrip qw/dump2perl perl2json .../>).
Section CAVEATS, under L</dump2perl>, describes how these
subs C<eval()> a string possibly coming from user,
possibly being unchecked.
=item * C<no-unicode-escape-permanently> : this is not an
export keyword/parameter but a parameter which affects
all the C<< *2dump* >> subs by setting unicode escaping
permanently to false. See L</EFFICIENCY>.
=item * C<unicode-escape-permanently> : this is not an
export keyword/parameter but a parameter which affects
all the C<< *2dump* >> subs by setting unicode escaping
permanently to true. See L</EFFICIENCY>.
=back
=head1 EFFICIENCY
The export keyword/parameter C<< no-unicode-escape-permanently >>
affects
all the C<< *2dump* >> subs by setting unicode escaping
permanently to false. This improves efficiency, although
one will ever need to
use this in extreme situations where a C<< *2dump* >>
sub is called repeatedly in a loop of
a few hundreds or thousands of iterations or more.
Each time a C<< *2dump* >> is called, the
C<< dont-bloody-escape-unicode >> flag is checked
and if it is set, then L<Data::Dumper>'s C<< qquote() >>
is overriden with C<< _qquote_redefinition_by_Corion() >>
just for that instance and will be restored as soon as
the dump is finished. Similarly, a filter for
not escaping unicode is added to L<Data::Dump>
just for that particular call and is removed immediately
after. This has some computational cost and can be
avoided completely by overriding the sub
and adding the filter once, at loading (in C<< import() >>).
The price to pay for this added efficiency is that
unicode in any dump will never be escaped (e.g. C<< \x{3b1}) >>,
but will be rendered (e.g. C<< α >>, a greek alpha). Always.
The option
C<< dont-bloody-escape-unicode >> will permanently be set to true.
Similarly, the export keyword/parameter
C<< unicode-escape-permanently >>
affects
all the C<< *2dump* >> subs by setting unicode escaping
permanently to true. This improves efficiency as well.
See L</BENCHMARKS> on how to find the fastest C<< *2dump* >>
sub.
=head1 BENCHMARKS
The special Makefile target C<< benchmarks >> will time
calls to each of the C<< *2dump* >> subs under
use Data::Roundtrip;
use Data::Roundtrip qw/no-unicode-escape-permanently/;
use Data::Roundtrip qw/unicode-escape-permanently/;
and for C<< 'dont-bloody-escape-unicode' => 0 >> and
C<< 'dont-bloody-escape-unicode' => 1 >>.
In general, L</perl2dump> is faster by 25% when one of the
permanent import parameters is used
(either of the last two cases above).
=head1 SUBROUTINES
=head2 C<perl2json>
my $ret = perl2json($perlvar, $optional_paramshashref)
lib/Data/Roundtrip.pm view on Meta::CPAN
=over 4
=item * C<$ret>
=back
Given an input C<$perlvar> (which can be a simple scalar or
a nested data structure, but not an object), it will return
the equivalent JSON string. In C<$optional_paramshashref>
one can specify whether to escape unicode with
C<< 'escape-unicode' => 1 >>
and/or prettify the returned result with C<< 'pretty' => 1 >>
and/or allow conversion of blessed objects with C<< 'convert_blessed' => 1 >>.
The latter is useful when the input (Perl) data structure
contains Perl objects (blessed refs!). But in addition to
setting it, each of the Perl objects (their class) must
implement a C<TO_JSON()> method which will simply convert
the object into a Perl data structure. For example, if
your object stores the important data in C<< $self->data >>
as a hash, then use this to return it
lib/Data/Roundtrip.pm view on Meta::CPAN
=over 4
=item * C<$ret>
=back
Given an input C<$perlvar> (which can be a simple scalar or
a nested data structure, but not an object), it will return
the equivalent YAML string. In C<$optional_paramshashref>
one can specify whether to escape unicode with
C<< 'escape-unicode' => 1 >>. Prettify is not supported yet.
The output can be fed to L</yaml2perl>
for getting the Perl variable back.
It returns the YAML string on success or C<undef> on failure.
=head2 C<yaml2perl>
my $ret = yaml2perl($yamlstring);
Arguments:
lib/Data/Roundtrip.pm view on Meta::CPAN
=over 4
=item * C<$ret>
=back
Given an input C<$perlvar> (which can be a simple scalar or
a nested data structure, but not an object), it will return
the equivalent string (via L<Data::Dumper>).
In C<$optional_paramshashref>
one can specify whether to escape unicode with
C<< 'dont-bloody-escape-unicode' => 0 >>,
(or C<< 'escape-unicode' => 1 >>). The DEFAULT
behaviour is to NOT ESCAPE unicode.
Additionally, use terse output with C<< 'terse' => 1 >> and remove
all the incessant indentation with C<< 'indent' => 1 >>
which unfortunately goes to the other extreme of
producing a space-less output, not fit for human consumption.
The output can be fed to L</dump2perl>
for getting the Perl variable back.
It returns the string representation of the input perl variable
on success or C<undef> on failure.
The output can be fed back to L</dump2perl>.
CAVEAT: when not escaping unicode (which is the default
behaviour), each call to this sub will override L<Data::Dumper>'s
C<qquote()> sub then
call L<Data::Dumper>'s C<Dumper()> and save its output to
a temporary variable, restore C<qquote()> sub to its original
code ref and return the
contents. This exercise is done every time this C<perl2dump()>
is called. It may be expensive. The alternative is
to redefine C<qquote()> once, when the module is loaded, with
all the side-effects this may cause.
Note that there are two other alternative subs which offer more-or-less
the same functionality and their output can be fed back to all the C<< dump2*() >>
subs. These are
L</perl2dump_filtered> which uses L<Data::Dump::Filtered>
to add a filter to control unicode escaping but
lacks in aesthetics and functionality and handling all the
cases Dump and Dumper do quite well.
There is also C<< perl2dump_homebrew() >> which
uses the same dump-recursively engine as
L</perl2dump_filtered>
but does not involve Data::Dump at all.
=head2 C<perl2dump_filtered>
lib/Data/Roundtrip.pm view on Meta::CPAN
Return value:
=over 4
=item * C<$ret>, the stringified version of the input Perl variable.
=back
This sub will take a Perl var (as a scalar or an arbitrarily nested data structure)
and emulate a very very basic
Dump/Dumper but with enforced rendering unicode (for keys or values or array items),
and not escaping unicode - this is not an option,
it returns a string representation of the input perl var
There are 2 obvious limitations:
=over 4
=item 1. indentation is very basic,
=item 2. it supports only scalars, hashes and arrays,
(which will dive into them no problem)
lib/Data/Roundtrip.pm view on Meta::CPAN
by first converting YAML to a Perl variable and then
converting that variable to JSON using L</perl2json>.
All the parameters supported by L</perl2json>
are accepted.
It returns the JSON string on success or C<undef> on failure.
=head2 C<json2json> C<yaml2yaml>
Transform a json or yaml string via pretty printing or via
escaping unicode or via un-escaping unicode. Parameters
like above will be accepted.
=head2 C<json2dump> C<dump2json> C<yaml2dump> C<dump2yaml>
These subs offer similar functionality as their counterparts
described above.
Section CAVEATS, under L</dump2perl>, describes how
C<dump2*()> subs C<eval()> a string possibly coming from user,
possibly being unchecked.
lib/Data/Roundtrip.pm view on Meta::CPAN
and is identical to L<Data::Dumper>'s C<Dumper()> output,
it will roundtrip back to the same string,
possibly with altered format via the parameters in C<$optional_paramshashref>.
For example:
my $dumpstr = '...';
my $newdumpstr = dump2dump(
$dumpstr,
{
'dont-bloody-escape-unicode' => 1,
'terse' => 0,
}
);
It returns the a dump string similar to
=head2 C<read_from_file>
lib/Data/Roundtrip.pm view on Meta::CPAN
=head1 BUGS
Please report any bugs or feature requests to C<bug-data-roundtrip at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Roundtrip>. I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SEE ALSO
=over 4
=item L<Convert JSON to Perl and back with unicode|https://perlmonks.org/?node_id=11115241>
=item L<RFC: PerlE<lt>-E<gt>JSONE<lt>-E<gt>YAMLE<lt>-E<gt>Dumper : roundtripping and possibly with unicode|https://perlmonks.org/?node_id=11115280>
=back
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Data::Roundtrip
lib/Data/Roundtrip.pm view on Meta::CPAN
=head1 ACKNOWLEDGEMENTS
Several Monks at L<PerlMonks.org | https://PerlMonks.org> (in no particular order):
=over 4
=item L<haukex|https://perlmonks.org/?node_id=830549>
=item L<Corion|https://perlmonks.org/?node_id=5348> (the
C<< _qquote_redefinition_by_Corion() >> which harnesses
L<Data::Dumper>'s incessant unicode escaping)
=item L<kcott|https://perlmonks.org/?node_id=861371>
(The EXPORT section among other suggestions)
=item L<jwkrahn|https://perlmonks.org/?node_id=540414>
=item L<leszekdubiel|https://perlmonks.org/?node_id=1164259>
=item L<marto|https://perlmonks.org/?node_id=324763>
script/json2json.pl view on Meta::CPAN
binmode STDIN, ':encoding(UTF-8)';
use Getopt::Long qw(:config no_ignore_case);
use Data::Roundtrip;
my $INPUT_STRING = undef;
my $INPUT_FILE = undef;
my $OUTPUT_FILE = undef;
my %params = (
'escape-unicode' => 0,
'pretty' => 0,
);
sub usage { return
"Usage : $0 [--I 'a-json-string' | --i 'afile.json'] [--o afile] [--(no-)escape-unicode|-e] [--(no-)pretty|-p]\n"
."\nIt will read a JSON string from command line (-I), or from a file (-i)\n"
."\nor from STDIN (beware 4K limit on linux terminal, see CAVEATS for workaround).\n"
."It will print its contents as JSON to STDOUT or to a file (--o).\n"
."It can escape/un-escape unicode characters (--escape-unicode) and/or do pretty-printing (--pretty).\n"
}
if( ! Getopt::Long::GetOptions(
'i=s' => \$INPUT_FILE,
'I=s' => sub { $INPUT_STRING = Encode::decode_utf8($_[1]) },
'o=s' => \$OUTPUT_FILE,
'pretty|p!' => \$params{'pretty'},
'escape-unicode|e!' => \$params{'escape-unicode'},
) ){ die usage() }
if( defined $INPUT_FILE ){
$INPUT_STRING = Data::Roundtrip::read_from_file($INPUT_FILE);
if( ! defined $INPUT_STRING ){ print STDERR "$0 : error, call to ".'Data::Roundtrip::read_from_file()'." has failed.\n"; exit(1) }
} elsif( ! defined $INPUT_STRING ){
# read from STDIN
$INPUT_STRING = do { local $/; <STDIN> }
}
script/json2json.pl view on Meta::CPAN
=head1 NAME
json2json.pl : re-format JSON data
=head1 VERSION
Version 0.30
=head1 SYNOPSIS
json2json.pl -i "input.json" -o "output.json" --escape-unicode --pretty
json2json.pl -e < "input.json" > "output.json"
# press CTRL-D when done typing JSON to STDIN
# input must be less than 4K long!
json2json.pl
# Read input from clipboard or write output to clipboard
# Only in: Unix / Linux / OSX
# (must have already installed xclip or xsel or pbpaste (on OSX))
script/json2json.pl view on Meta::CPAN
=item * C<--i filename> : specify a filename which contains a JSON
data structure.
=item * C<--I "string"> : specify a string which contains a JSON
data structure.
=item * C<--o outputfilename> : specify the output filename to write
the result to, which will be the reformatted JSON.
=item * C<--escape-unicode> : it will escape all unicode characters, and
convert them to something like "\u0386". This is the default option.
=item * C<--no-escape-unicode> : it will NOT escape unicode characters. Output
will not contain "\u0386" or "\x{386}" but "α" (that's a greek alpha). This is the default
option.
=item * C<--pretty> / C<--no-pretty> : write this JSON pretty, line breaks, indendations, "the full catastrophe".
The second is the default.
=back
Input can be read from an input file (--i), from a string at the
command line (--I) (properly quoted!), from STDIN (which also includes
script/json2perl.pl view on Meta::CPAN
binmode STDIN, ':encoding(UTF-8)';
use Getopt::Long qw(:config no_ignore_case);
use Data::Roundtrip;
my $INPUT_STRING = undef;
my $INPUT_FILE = undef;
my $OUTPUT_FILE = undef;
my %params = (
'dont-bloody-escape-unicode' => 1,
'terse' => 0,
'indent' => 1,
);
sub usage { return
"Usage : $0 [--I 'a-json-string' | --i 'afile.json'] [--o afile] [--(no-)escape-unicode|-e] [--(no-)pretty] [--(no-)terse] [--(no-)indent]\n"
."\nIt will read a JSON string from command line (-I), or from a file (-i)\n"
."\nor from STDIN (beware 4K limit on linux terminal, see CAVEATS for workaround).\n"
."It will print its contents as a Perl variable (dump) to STDOUT or to a file (--o).\n"
."It can escape/un-escape unicode characters (--escape-unicode) and/or --terse and/or --indent.\n"
}
if( ! Getopt::Long::GetOptions(
'i=s' => \$INPUT_FILE,
'I=s' => sub { $INPUT_STRING = Encode::decode_utf8($_[1]) },
'o=s' => \$OUTPUT_FILE,
'terse|r!' => \$params{'terse'},
'indent|d!' => \$params{'indent'},
'escape-unicode|e!' => sub { $params{'dont-bloody-escape-unicode'} = $_[1] ? 0 : 1 },
) ){ die usage() }
if( defined $INPUT_FILE ){
$INPUT_STRING = Data::Roundtrip::read_from_file($INPUT_FILE);
if( ! defined $INPUT_STRING ){ print STDERR "$0 : error, call to ".'Data::Roundtrip::read_from_file()'." has failed.\n"; exit(1) }
} elsif( ! defined $INPUT_STRING ){
# read from STDIN
$INPUT_STRING = do { local $/; <STDIN> }
}
script/json2perl.pl view on Meta::CPAN
=head1 NAME
json2perl.pl : convert JSON data to a Perl variable (dump) which can be parsed or eval'ed by any Perl script.
=head1 VERSION
Version 0.30
=head1 SYNOPSIS
json2perl.pl -i "input.json" -o "output.pl" --no-escape-unicode --terse --no-indent
json2perl.pl -e < "input.json" > "output.pl"
# press CTRL-D when done typing JSON to STDIN
# input must be less than 4K long!
json2perl.pl
# Read input from clipboard or write output to clipboard
# Only in: Unix / Linux / OSX
# (must have already installed xclip or xsel or pbpaste (on OSX))
script/json2perl.pl view on Meta::CPAN
=item * C<--i filename> : specify a filename which contains a JSON
data structure.
=item * C<--I "string"> : specify a string which contains a JSON
data structure.
=item * C<--o outputfilename> : specify the output filename to write
the result to, which will be as a Perl variable, as a dump,
which can be parsed or eval'ed from any Perl script.
=item * C<--escape-unicode> : it will escape all unicode characters, and
convert them to something like "\u0386". This is the default option.
=item * C<--no-escape-unicode> : it will NOT escape unicode characters. Output
will not contain "\u0386" or "\x{386}" but "α" (that's a greek alpha).
=item * C<--terse> / C<--no-terse> : Terse form of output (no $VAR1 for example).
The second is the default option.
=item * C<--indent> / C<--no-indent> : do not use indentation. The first is the default option.
=back
Input can be read from an input file (--i), from a string at the
script/json2yaml.pl view on Meta::CPAN
binmode STDIN, ':encoding(UTF-8)';
use Getopt::Long qw(:config no_ignore_case);
use Data::Roundtrip;
my $INPUT_STRING = undef;
my $INPUT_FILE = undef;
my $OUTPUT_FILE = undef;
my %params = (
'escape-unicode' => 0,
# 'pretty' => 0, # not supported
);
sub usage { return
"Usage : $0 [--I 'a-json-string' | --i 'afile.json'] [--o afile] [--(no-)escape-unicode|-e]\n"
."\nIt will read a JSON string from command line (-I), or from a file (-i)\n"
."\nor from STDIN (beware 4K limit on linux terminal, see CAVEATS for workaround).\n"
."It will print its contents as YAML to STDOUT or to a file (--o).\n"
."It can escape/un-escape unicode characters (--escape-unicode). Pretty-printing is not supported.\n"
}
if( ! Getopt::Long::GetOptions(
'i=s' => \$INPUT_FILE,
'I=s' => sub { $INPUT_STRING = Encode::decode_utf8($_[1]) },
'o=s' => \$OUTPUT_FILE,
'pretty|p!' => sub { warn "--pretty has no effect for converting to YAML and will be ignored.\n" },
'escape-unicode|e!' => \$params{'escape-unicode'},
) ){ die usage() }
if( defined $INPUT_FILE ){
$INPUT_STRING = Data::Roundtrip::read_from_file($INPUT_FILE);
if( ! defined $INPUT_STRING ){ print STDERR "$0 : error, call to ".'Data::Roundtrip::read_from_file()'." has failed.\n"; exit(1) }
} elsif( ! defined $INPUT_STRING ){
# read from STDIN
$INPUT_STRING = do { local $/; <STDIN> }
}
script/json2yaml.pl view on Meta::CPAN
=head1 NAME
json2yaml.pl : convert JSON to YAML with formatting options.
=head1 VERSION
Version 0.30
=head1 SYNOPSIS
json2yaml.pl -i "input.json" -o "output.yaml" --(no-)escape-unicode
json2yaml.pl -e < "input.json" > "output.yaml"
# press CTRL-D when done typing JSON to STDIN
# input must be less than 4K long!
json2yaml.pl
# Read input from clipboard or write output to clipboard
# Only in: Unix / Linux / OSX
# (must have already installed xclip or xsel or pbpaste (on OSX))
script/json2yaml.pl view on Meta::CPAN
=item * C<--i filename> : specify a filename which contains a JSON
data structure.
=item * C<--I "string"> : specify a string which contains a JSON
data structure.
=item * C<--o outputfilename> : specify the output filename to write
the result to, which will be YAML.
=item * C<--escape-unicode> : it will escape all unicode characters, and
convert them to something like "\u0386". This is the default option.
=item * C<--no-escape-unicode> : it will NOT escape unicode characters. Output
will not contain "\u0386" or "\x{386}" but "α" (that's a greek alpha).
=back
Input can be read from an input file (--i), from a string at the
command line (--I) (properly quoted!), from STDIN (which also includes
a file redirection C<< json2yaml.pl < inputfile.json > outputfile.yaml >>
For more information see L<Data::Roundtrip>.
script/perl2json.pl view on Meta::CPAN
binmode STDIN, ':encoding(UTF-8)';
use Getopt::Long qw(:config no_ignore_case);
use Data::Roundtrip;
my $INPUT_STRING = undef;
my $INPUT_FILE = undef;
my $OUTPUT_FILE = undef;
my %params = (
'dont-bloody-escape-unicode' => 1,
'pretty' => 0,
);
sub usage { return
"Usage : $0 [--I 'a-perl-var-as-string' | --i 'afile.pl'] [--o afile.json] [--(no-)escape-unicode|-e] [--(no-)pretty]\n"
."\nIt will read a Perl variable as a string from command line (-I), or a file (-i)\n"
."\nor from STDIN (beware 4K limit on linux terminal, see CAVEATS for workaround).\n"
."It will print its JSON equivalent to STDOUT or to a file (--o).\n"
."It can optionally escape unicode characters (--escape-unicode) and/or do pretty-printing (--pretty).\n"
}
if( ! Getopt::Long::GetOptions(
'i=s' => \$INPUT_FILE,
'I=s' => sub { $INPUT_STRING = Encode::decode_utf8($_[1]) },
'o=s' => \$OUTPUT_FILE,
'pretty|p!' => \$params{'pretty'},
'escape-unicode|e!' => sub { $params{'dont-bloody-escape-unicode'} = $_[1] ? 0 : 1 },
) ){ die usage() }
if( defined $INPUT_FILE ){
$INPUT_STRING = Data::Roundtrip::read_from_file($INPUT_FILE);
if( ! defined $INPUT_STRING ){ print STDERR "$0 : error, call to ".'Data::Roundtrip::read_from_file()'." has failed.\n"; exit(1) }
} elsif( ! defined $INPUT_STRING ){
# read from STDIN
$INPUT_STRING = do { local $/; <STDIN> }
}
script/perl2json.pl view on Meta::CPAN
=head1 NAME
perl2json.pl : convert a Perl data structure dump to JSON
=head1 VERSION
Version 0.30
=head1 SYNOPSIS
perl2json.pl -i "perl-data-structure.pl" -o "output.json" --escape-unicode --pretty
perl2json.pl -e < "perl-data-structure.pl" > "output.json"
# press CTRL-D when done typing json to STDIN
# input must be less than 4K long!
perl2json.pl
# Read input from clipboard or write output to clipboard
# Only in: Unix / Linux / OSX
# (must have already installed xclip or xsel or pbpaste (on OSX))
script/perl2json.pl view on Meta::CPAN
data structure in text representation, not as a (binary) serialised
object, as one would have used in a Perl script.
=item * C<--I "string"> : specify a string which contains a Perl
data structure in text representation, not as a (binary) serialised
object. But exactly as one would have used in a Perl script.
=item * C<--o outputfilename> : specify the output filename to write
the result to.
=item * C<--escape-unicode> / C<--no-escape-unicode> : it will escape all unicode characters, and
convert them to something like "\u0386"
=item * C<--pretty> / C<--no-pretty> : write this JSON pretty, line breaks, indendations, "the full catastrophe"
=back
Input can be read from an input file (--i), from a string at the
command line (--I) (properly quoted!), from STDIN (which also includes
a file redirection C<< json2json.pl < inputfile.json > outputfile.json >>
script/yaml2json.pl view on Meta::CPAN
binmode STDIN, ':encoding(UTF-8)';
use Getopt::Long qw(:config no_ignore_case);
use Data::Roundtrip;
my $INPUT_STRING = undef;
my $INPUT_FILE = undef;
my $OUTPUT_FILE = undef;
my %params = (
'escape-unicode' => 0,
'pretty' => 0,
);
sub usage { return
"Usage : $0 [--I 'a-yaml-string' | --i 'afile.yaml'] [--o afile] [--(no-)escape-unicode|-e] [--(no-)pretty]\n"
."\nIt will read a YAML string from command line (-I), or from a file (-i)\n"
."\nor from STDIN (beware 4K limit on linux terminal, see CAVEATS for workaround).\n"
."It will print its contents as YAML to STDOUT or to a file (--o).\n"
."It can escape/un-escape unicode characters (--escape-unicode) and/or do pretty-printing (--pretty).\n"
}
if( ! Getopt::Long::GetOptions(
'i=s' => \$INPUT_FILE,
'I=s' => sub { $INPUT_STRING = Encode::decode_utf8($_[1]) },
'o=s' => \$OUTPUT_FILE,
'pretty|p!' => \$params{'pretty'},
'escape-unicode|e!' => \$params{'escape-unicode'},
) ){ die usage() }
if( defined $INPUT_FILE ){
$INPUT_STRING = Data::Roundtrip::read_from_file($INPUT_FILE);
if( ! defined $INPUT_STRING ){ print STDERR "$0 : error, call to ".'Data::Roundtrip::read_from_file()'." has failed.\n"; exit(1) }
} elsif( ! defined $INPUT_STRING ){
# read from STDIN
$INPUT_STRING = do { local $/; <STDIN> }
}
script/yaml2json.pl view on Meta::CPAN
=head1 NAME
yaml2json.pl : convert YAML to JSON with formatting options
=head1 VERSION
Version 0.30
=head1 SYNOPSIS
yaml2json.pl -i "input.yaml" -o "output.json" --escape-unicode --pretty
yaml2json.pl -e < "input.yaml" > "output.json"
# press CTRL-D when done typing YAML to STDIN
# input must be less than 4K long!
yaml2json.pl
# Read input from clipboard or write output to clipboard
# Only in: Unix / Linux / OSX
# (must have already installed xclip or xsel or pbpaste (on OSX))
script/yaml2json.pl view on Meta::CPAN
=item * C<--i filename> : specify a filename which contains a YAML
data structure.
=item * C<--I "string"> : specify a string which contains a YAML
data structure.
=item * C<--o outputfilename> : specify the output filename to write
the result to, which will be JSON.
=item * C<--escape-unicode> : it will escape all unicode characters, and
convert them to something like "\u0386". This is the default option.
=item * C<--no-escape-unicode> : it will NOT escape unicode characters. Output
will not contain "\u0386" or "\x{386}" but "α" (that's a greek alpha).
=item * C<--pretty> / C<--no-pretty> : write this JSON pretty, line breaks, indendations, "the full catastrophe".
The C<--no-pretty> option will produce terse output, no spaces or line breaks for example.
The second option is the default.
=back
Input can be read from an input file (--i), from a string at the
command line (--I) (properly quoted!), from STDIN (which also includes
script/yaml2perl.pl view on Meta::CPAN
binmode STDIN, ':encoding(UTF-8)';
use Getopt::Long qw(:config no_ignore_case);
use Data::Roundtrip;
my $INPUT_STRING = undef;
my $INPUT_FILE = undef;
my $OUTPUT_FILE = undef;
my %params = (
'dont-bloody-escape-unicode' => 1,
'terse' => 0,
'indent' => 1,
);
sub usage { return
"Usage : $0 [--I 'a-yaml-string' | --i 'afile.yaml'] [--o afile] [--(no-)escape-unicode|-e] [--(no-)pretty] [--(no-)terse] [--(no-)indent]\n"
."\nIt will read a YAML string from command line (-I), or from a file (-i)\n"
."\nor from STDIN (beware 4K limit on linux terminal, see CAVEATS for workaround).\n"
."It will print its contents as a Perl variable (dump) to STDOUT or to a file (--o).\n"
."It can escape/un-escape unicode characters (--escape-unicode) and/or --terse and --no-indent.\n"
}
if( ! Getopt::Long::GetOptions(
'i=s' => \$INPUT_FILE,
'I=s' => sub { $INPUT_STRING = Encode::decode_utf8($_[1]) },
'o=s' => \$OUTPUT_FILE,
'terse|r!' => \$params{'terse'},
'indent|d!' => \$params{'indent'},
'escape-unicode|e!' => sub { $params{'dont-bloody-escape-unicode'} = $_[1] ? 0 : 1 },
) ){ die usage() }
if( defined $INPUT_FILE ){
$INPUT_STRING = Data::Roundtrip::read_from_file($INPUT_FILE);
if( ! defined $INPUT_STRING ){ print STDERR "$0 : error, call to ".'Data::Roundtrip::read_from_file()'." has failed.\n"; exit(1) }
} elsif( ! defined $INPUT_STRING ){
# read from STDIN
$INPUT_STRING = do { local $/; <STDIN> }
}
script/yaml2perl.pl view on Meta::CPAN
=head1 NAME
yaml2perl.pl : convert YAML data to a Perl variable (dump) which can be parsed or eval'ed by any Perl script.
=head1 VERSION
Version 0.30
=head1 SYNOPSIS
yaml2perl.pl -i "input.yaml" -o "output.perl" --no-escape-unicode --terse --no-indent
yaml2perl.pl -e < "input.yaml" > "output.pl"
# press CTRL-D when done typing YAML to STDIN
# input must be less than 4K long!
yaml2perl.pl
# Read input from clipboard or write output to clipboard
# Only in: Unix / Linux / OSX
# (must have already installed xclip or xsel or pbpaste (on OSX))
script/yaml2perl.pl view on Meta::CPAN
=item * C<--i filename> : specify a filename which contains a YAML
data structure.
=item * C<--I "string"> : specify a string which contains a YAML
data structure.
=item * C<--o outputfilename> : specify the output filename to write
the result to, which will be as a Perl variable, as a dump,
which can be parsed or eval'ed from any Perl script.
=item * C<--escape-unicode> : it will escape all unicode characters, and
convert them to something like "\u0386". This is the default option.
=item * C<--no-escape-unicode> : it will NOT escape unicode characters. Output
will not contain "\u0386" or "\x{386}" but "α" (that's a greek alpha).
=item * C<--terse> / C<--no-terse> : Terse form of output (no $VAR1). The second is the default option.
=item * C<--indent> / C<--no-indent> : do not use indentation. The first is the default option.
=back
Input can be read from an input file (--i), from a string at the
command line (--I) (properly quoted!), from STDIN (which also includes
t/01-basic.t view on Meta::CPAN
# yaml2json
$result = Data::Roundtrip::yaml2json($yaml_string);
ok(defined $result, "yaml2json() called."); $num_tests++;
ok($result eq $json_string, "perl2yaml() checked".($verbose?" (got: '$result', expected: '$json_string')":"")."."); $num_tests++;
# json2yaml
$result = Data::Roundtrip::json2yaml($json_string);
ok(defined $result, "json2yaml() called."); $num_tests++;
ok($result eq $yaml_string, "perl2yaml() checked".($verbose?" (got: '$result', expected: '$yaml_string')":"")."."); $num_tests++;
# perl2dump and dump2perl WITH unicode escaping
# (that's default Data::Dumper behaviour)
# this is what you must see:
# "abc-\x{3b1}\x{3b2}\x{3b3}" => "\x{3c7}\x{3c8}\x{3b6}-xyz"
my $adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>1, 'dont-bloody-escape-unicode'=>0}
);
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump=~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# dump2perl
$result = Data::Roundtrip::dump2perl($adump);
ok(defined $result, "dump2perl() called."); $num_tests++;
for my $k (keys %$result){
ok(exists $perl_var->{$k}, "perl2dump() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result->{$k}, "perl2dump() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result->{$k}, "perl2dump() and dump2perl() key exists (other way round)."); $num_tests++;
}
# perl2dump and dump2perl WITHOUT unicode escaping
# (that's NOT default Data::Dumper behaviour)
# that means to get this output:
# "abc-αβγ" => "ÏÏζ-xyz"
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>1, 'dont-bloody-escape-unicode'=>1}
);
ok(defined($adump), "perl2dump() called."); $num_tests++;
ok($adump!~/\\x\{3b1\}/, "perl2dump() unicode not escaped."); $num_tests++;
# dump2perl
$result = Data::Roundtrip::dump2perl($adump);
ok(defined $result, "dump2perl() called".($verbose?" ($adump)":"")."."); $num_tests++;
for my $k (keys %$result){
ok(exists $perl_var->{$k}, "perl2dump() and dump2perl() key exists".($verbose?$k:"")."."); $num_tests++;
ok($perl_var->{$k} eq $result->{$k}, "perl2dump() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result->{$k}, "perl2dump() and dump2perl() key exists (other way round)."); $num_tests++;
}
# perl2dump and dump2perl WITHOUT unicode escaping
# but complex input.
# (that's NOT default Data::Dumper behaviour)
# that means to get this output:
# "abc-αβγ" => "ÏÏζ-xyz"
$perl_var = {};
$perl_var->{'key1'} = <<EOP;
\"\\u0398\\u03b5\\u03c4\\u03b9\\u03ba\\u03ac Normalized\\"},\\"Name\\":\\"dashboard_view.\\u0398\\u03b5\\u03c4\\u03b9\\u03ba\\u03ac Normalized\\"},{\\"Measure\\":{\\"Expression\\":{\\"SourceRef\\":{\\"Source\\":\\"d\\"}},\\"Property\\":\\"\\u0394\\u0...
EOP
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>1, 'dont-bloody-escape-unicode'=>1}
);
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump!~/\\x\{3b1\}/, "perl2dump() unicode not escaped."); $num_tests++;
# dump2perl
$result = Data::Roundtrip::dump2perl($adump);
ok(defined $result, "dump2perl() called."); $num_tests++;
for my $k (keys %$result){
ok(exists $perl_var->{$k}, "perl2dump() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result->{$k}, "perl2dump() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result->{$k}, "perl2dump() and dump2perl() key exists (other way round)."); $num_tests++;
}
# check terse and indent modes
# use a perl var which is complex enough to cause indent and terse differences
$perl_var = {$abc => $xyz, $xyz => $abc, "123" => $xyz, "545" => $abc, "arr" => [$abc, $xyz, '123', [1,2,3], 0]};
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>1, 'dont-bloody-escape-unicode'=>0, 'indent'=>0});
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump=~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# terse: do we have $VAR1?
ok($adump!~/^\$VAR1/, "perl2dump() is in terse mode".($verbose?" ($adump)":"")."."); $num_tests++;
# indent: do we have new lines?
ok($adump!~/\r\n|\r|\n/, "perl2dump() allows indent".($verbose?" ($adump)":"")."."); $num_tests++;
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>1, 'dont-bloody-escape-unicode'=>1, 'indent'=>0});
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump!~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# terse: do we have $VAR1?
ok($adump!~/^\$VAR1/, "perl2dump() is in terse mode".($verbose?" ($adump)":"")."."); $num_tests++;
# indent: do we have new lines?
ok($adump!~/\r\n|\r|\n/, "perl2dump() allows indent".($verbose?" ($adump)":"")."."); $num_tests++;
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>0, 'dont-bloody-escape-unicode'=>0, 'indent'=>0});
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump=~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# terse: do we have $VAR1?
ok($adump=~/^\$VAR1/, "perl2dump() is in terse mode".($verbose?" ($adump)":"")."."); $num_tests++;
# indent: do we have new lines?
ok($adump!~/\r\n|\r|\n/, "perl2dump() allows indent".($verbose?" ($adump)":"")."."); $num_tests++;
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>0, 'dont-bloody-escape-unicode'=>1, 'indent'=>0});
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump!~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# terse: do we have $VAR1?
ok($adump=~/^\$VAR1/, "perl2dump() is in terse mode".($verbose?" ($adump)":"")."."); $num_tests++;
# indent: do we have new lines?
ok($adump!~/\r\n|\r|\n/, "perl2dump() allows indent".($verbose?" ($adump)":"")."."); $num_tests++;
## now with no indent
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>1, 'dont-bloody-escape-unicode'=>0, 'indent'=>1});
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump=~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# terse: do we have $VAR1?
ok($adump!~/^\$VAR1/, "perl2dump() is in terse mode".($verbose?" ($adump)":"")."."); $num_tests++;
# indent: do we have new lines?
ok($adump=~/\r\n|\r|\n/, "perl2dump() allows indent".($verbose?" ($adump)":"")."."); $num_tests++;
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>1, 'dont-bloody-escape-unicode'=>1, 'indent'=>1});
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump!~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# terse: do we have $VAR1?
ok($adump!~/^\$VAR1/, "perl2dump() is in terse mode".($verbose?" ($adump)":"")."."); $num_tests++;
# indent: do we have new lines?
ok($adump=~/\r\n|\r|\n/, "perl2dump() allows indent".($verbose?" ($adump)":"")."."); $num_tests++;
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>0, 'dont-bloody-escape-unicode'=>0, 'indent'=>1});
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump=~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# terse: do we have $VAR1?
ok($adump=~/^\$VAR1/, "perl2dump() is in terse mode".($verbose?" ($adump)":"")."."); $num_tests++;
# indent: do we have new lines?
ok($adump=~/\r\n|\r|\n/, "perl2dump() allows indent".($verbose?" ($adump)":"")."."); $num_tests++;
$adump = Data::Roundtrip::perl2dump($perl_var,
{'terse'=>0, 'dont-bloody-escape-unicode'=>1, 'indent'=>1});
ok(defined $adump, "perl2dump() called."); $num_tests++;
ok($adump!~/(\\x\{3b1\})/, "perl2dump() unicode not escaped".($verbose?" ($adump)":"")."."); $num_tests++;
# terse: do we have $VAR1?
ok($adump=~/^\$VAR1/, "perl2dump() is in terse mode".($verbose?" ($adump)":"")."."); $num_tests++;
# indent: do we have new lines?
ok($adump=~/\r\n|\r|\n/, "perl2dump() allows indent".($verbose?" ($adump)":"")."."); $num_tests++;
if( $verbose == 0 ){
my @tests = Test::More->builder->details;
for my $test (@tests) {
if(! $test->{ok} ){
# a test failed, rerun with verbose on
t/02-random-data-structure.t view on Meta::CPAN
#!perl -T
use 5.008;
use strict;
use warnings;
our $VERSION='0.30';
# NO UTF8 here, we are checking with random
# data structure which provides no unicode
# there is a separate file for testing with unicode
my $MAXTRIALS = 1000;
#### nothing to change below
use Test::More;
use Data::Dump qw/pp/;
my $num_tests = 0;
t/02-random-data-structure.t view on Meta::CPAN
my $result = $aperl2Xfuncstr->($perl_var);
ok(defined $result, "$aperl2Xfunc() called.") or BAIL_OUT("$aperl2Xfunc() : (seed=$seed) failed for this var:\n".pp($perl_var)); $num_tests++;
my $aX2perlfunc = $testfuncs{$aperl2Xfunc};
my $aX2perlfuncstr = 'Data::Roundtrip::'.$aX2perlfunc;
my $back = $aX2perlfuncstr->($result);
ok(defined $back, "$aX2perlfunc() called.") or BAIL_OUT("$aX2perlfuncstr() : (seed=$seed) failed for this string:\n".$result); $num_tests++;
ok(ref($back) eq ref($perl_var), "checking same rountrip refs ".ref($back)." and ".ref($perl_var)."."); $num_tests++;
}
$params = {
'Terse' => 1,
'dont-bloody-escape-unicode' => 1,
'pretty' => 1,
'escape-unicode' => 1,
};
for my $aperl2Xfunc (sort keys %testfuncs){
no strict 'refs';
my $aperl2Xfuncstr = 'Data::Roundtrip::'.$aperl2Xfunc;
my $result = $aperl2Xfuncstr->($perl_var, $params);
ok(defined $result, "$aperl2Xfunc() called.") or BAIL_OUT("$aperl2Xfunc() : (seed=$seed) failed for this var:\n".pp($perl_var)); $num_tests++;
my $aX2perlfunc = $testfuncs{$aperl2Xfunc};
my $aX2perlfuncstr = 'Data::Roundtrip::'.$aX2perlfunc;
my $back = $aX2perlfuncstr->($result, $params);
ok(defined $back, "$aX2perlfunc() called.") or BAIL_OUT("$aX2perlfunc() : (seed=$seed) failed for this string:\n".$result); $num_tests++;
t/03-random-data-structure-UTF8.t view on Meta::CPAN
my $num_tests = 0;
use Data::Roundtrip;
use Data::Random::Structure::UTF8;
my $randomiser = Data::Random::Structure::UTF8->new(
max_depth => 50,
max_elements => 200,
'only-unicode' => 1,
);
ok(defined $randomiser, 'Data::Random::Structure::UTF8->new()'." called."); $num_tests++;
my $perl_var = $randomiser->generate();
ok(defined $perl_var, "generate() called."); $num_tests++;
my %testfuncs;
for my $k (sort grep {/^perl2/} keys %Data::Roundtrip::){
my @x = split /2/, $k;
my $newsub = join('2',reverse @x);
next unless Data::Roundtrip->can($newsub);
t/03-random-data-structure-UTF8.t view on Meta::CPAN
my $astestfuncstr = 'Data::Roundtrip::'.$astestfunc;
my $result = $astestfuncstr->($perl_var);
ok(defined $result, "$astestfunc() called."); $num_tests++;
my $areversefunc = $testfuncs{$astestfunc};
my $areversefuncstr = 'Data::Roundtrip::'.$areversefunc;
my $back = $areversefuncstr->($result);
ok(defined $back, "$areversefunc() called."); $num_tests++;
}
$params = {
'Terse' => 1,
'dont-bloody-escape-unicode' => 1,
'pretty' => 1,
'escape-unicode' => 1,
};
for my $astestfunc (sort keys %testfuncs){
no strict 'refs';
my $astestfuncstr = 'Data::Roundtrip::'.$astestfunc;
my $result = $astestfuncstr->($perl_var, $params);
ok(defined $result, "$astestfunc() called."); $num_tests++;
my $areversefunc = $testfuncs{$astestfunc};
my $areversefuncstr = 'Data::Roundtrip::'.$areversefunc;
my $back = $areversefuncstr->($result, $params);
ok(defined $back, "$areversefunc() called."); $num_tests++;
}
$params = {
'Terse' => 0,
'dont-bloody-escape-unicode' => 0,
'pretty' => 0,
'escape-unicode' => 0,
};
for my $astestfunc (sort keys %testfuncs){
no strict 'refs';
my $astestfuncstr = 'Data::Roundtrip::'.$astestfunc;
my $result = $astestfuncstr->($perl_var, $params);
ok(defined $result, "$astestfunc() called."); $num_tests++;
my $areversefunc = $testfuncs{$astestfunc};
my $areversefuncstr = 'Data::Roundtrip::'.$areversefunc;
my $back = $areversefuncstr->($result, $params);
ok(defined $back, "$areversefunc() called."); $num_tests++;
t/05-perl2dump-no-escape-unicode-temporarily.t view on Meta::CPAN
$abc: $xyz
EOS
#$yaml_string =~ s/\s*$//;
my $perl_var = {$abc => $xyz};
# without escaping, no \x{3b1} !
my $adump_p1 = perl2dump($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 1,
}
);
ok(defined $adump_p1, "perl2dump() called."); $num_tests++;
ok($adump_p1!~/\\x\{3b1\}/i, "perl2dump() unicode escaped."); $num_tests++;
my $adump_p2 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 1,
}
);
ok(defined $adump_p2, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p2!~/(\\x\{3b1\})/i, "perl2dump_filtered() unicode escaped."); $num_tests++;
# dump2perl
my $result_p1 = dump2perl($adump_p1);
ok(defined $result_p1, "dump2perl() called."); $num_tests++;
for my $k (keys %$result_p1){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p1->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p1->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
t/05-perl2dump-no-escape-unicode-temporarily.t view on Meta::CPAN
for my $k (keys %$result_p2){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p2->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p2->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
}
### now with escaping, because it is not permanent
# it will be escaped if we ask for it
# 'dont-bloody-escape-unicode'=>0 will have an effect
$adump_p1 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 0,
}
);
ok(defined $adump_p1, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p1=~/\\x\{3b1\}/i, "perl2dump_filtered() unicode not escaped."); $num_tests++;
$adump_p2 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 0,
}
);
ok(defined $adump_p2, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p2=~/\\x\{3b1\}/i, "perl2dump_filtered() unicode not escaped."); $num_tests++;
# dump2perl
$result_p1 = dump2perl($adump_p1);
ok(defined $result_p1, "dump2perl() called."); $num_tests++;
for my $k (keys %$result_p1){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p1->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p1->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
t/06-perl2dump-no-escape-unicode-permanently.t view on Meta::CPAN
our $VERSION='0.30';
use Test::More;
use Test2::Plugin::UTF8;
my $num_tests = 0;
# the default is to permanently overwrite dumper's qquote()
# and permanently add a filter to Dump.
use Data::Roundtrip qw/:all dump2perl no-unicode-escape-permanently/;
my $abc = "abc-αβγ";
my $xyz = "ÏÏζ-xyz";
my $json_string = <<EOS;
{"$abc":"$xyz"}
EOS
$json_string =~ s/\s*$//;
my $yaml_string = <<EOS;
t/06-perl2dump-no-escape-unicode-permanently.t view on Meta::CPAN
$abc: $xyz
EOS
#$yaml_string =~ s/\s*$//;
my $perl_var = {$abc => $xyz};
# without escaping, no \x{3b1} !
my $adump_p1 = perl2dump($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 1,
}
);
ok(defined $adump_p1, "perl2dump() called."); $num_tests++;
ok($adump_p1!~/\\x\{3b1\}/i, "perl2dump() unicode not escaped."); $num_tests++;
my $adump_p2 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 1,
}
);
ok(defined $adump_p2, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p2!~/(\\x\{3b1\})/i, "perl2dump_filtered() unicode not escaped."); $num_tests++;
# dump2perl
my $result_p1 = dump2perl($adump_p1);
ok(defined $result_p1, "dump2perl() called."); $num_tests++;
for my $k (keys %$result_p1){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p1->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p1->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
t/06-perl2dump-no-escape-unicode-permanently.t view on Meta::CPAN
for my $k (keys %$result_p2){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p2->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p2->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
}
### now with escaping but because it is permanent,
# it will not be escaped,
# 'dont-bloody-escape-unicode'=>0 will have no effect
$adump_p1 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 0,
}
);
ok(defined $adump_p1, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p1!~/\\x\{3b1\}/i, "perl2dump_filtered() unicode not escaped."); $num_tests++;
$adump_p2 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 0,
}
);
ok(defined $adump_p2, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p2!~/\\x\{3b1\}/i, "perl2dump_filtered() unicode not escaped."); $num_tests++;
# dump2perl
$result_p1 = dump2perl($adump_p1);
ok(defined $result_p1, "dump2perl() called."); $num_tests++;
for my $k (keys %$result_p1){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p1->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p1->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
t/07-perl2dump-escape-unicode-permanently.t view on Meta::CPAN
use utf8;
our $VERSION='0.30';
use Test::More;
use Test2::Plugin::UTF8;
#use Test::Deep;
my $num_tests = 0;
# always escape unicode (default Dump and Dumper behaviour)
# this is as efficient as no-unicode-escape-permanently
use Data::Roundtrip qw/:all dump2perl unicode-escape-permanently/;
my $abc = "abc-αβγ";
my $xyz = "ÏÏζ-xyz";
my $json_string = <<EOS;
{"$abc":"$xyz"}
EOS
$json_string =~ s/\s*$//;
my $yaml_string = <<EOS;
t/07-perl2dump-escape-unicode-permanently.t view on Meta::CPAN
$abc: $xyz
EOS
#$yaml_string =~ s/\s*$//;
my $perl_var = {$abc => $xyz};
# without escaping, no \x{3b1} !
my $adump_p1 = perl2dump($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 1,
}
);
ok(defined $adump_p1, "perl2dump() called."); $num_tests++;
ok($adump_p1=~/\\x\{3b1\}/i, "perl2dump() unicode escaped."); $num_tests++;
my $adump_p2 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 1,
}
);
ok(defined $adump_p2, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p2=~/(\\x\{3b1\})/i, "perl2dump_filtered() unicode escaped."); $num_tests++;
# dump2perl
my $result_p1 = dump2perl($adump_p1);
ok(defined $result_p1, "dump2perl() called."); $num_tests++;
for my $k (keys %$result_p1){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p1->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p1->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
t/07-perl2dump-escape-unicode-permanently.t view on Meta::CPAN
for my $k (keys %$result_p2){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p2->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p2->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
}
### now with escaping but because it is permanent,
# it will not be escaped,
# 'dont-bloody-escape-unicode'=>0 will have no effect
$adump_p1 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 0,
}
);
ok(defined $adump_p1, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p1=~/\\x\{3b1\}/i, "perl2dump_filtered() unicode escaped."); $num_tests++;
$adump_p2 = perl2dump_filtered($perl_var,
{
'terse'=> 1,
'dont-bloody-escape-unicode'=> 0,
}
);
ok(defined $adump_p2, "perl2dump_filtered() called."); $num_tests++;
ok($adump_p2=~/\\x\{3b1\}/i, "perl2dump_filtered() unicode escaped."); $num_tests++;
# dump2perl
$result_p1 = dump2perl($adump_p1);
ok(defined $result_p1, "dump2perl() called."); $num_tests++;
for my $k (keys %$result_p1){
ok(exists $perl_var->{$k}, "perl2dump_filtered() and dump2perl() key exists."); $num_tests++;
ok($perl_var->{$k} eq $result_p1->{$k}, "perl2dump_filtered() and dump2perl() values are the same."); $num_tests++;
}
for my $k (keys %$perl_var){
ok(exists $result_p1->{$k}, "perl2dump_filtered() and dump2perl() key exists (other way round)."); $num_tests++;
t/13-yaml-tricky-cases.t view on Meta::CPAN
$yamlstr = perl2yaml($perl);
ok(defined($yamlstr), 'perl2yaml()'." : called and got defined result");
ok($yamlstr =~ /^\-\-\-/, 'perl2yaml()'." : called and looks like a yaml string");
$newperl = yaml2perl($yamlstr);
ok(defined($newperl), 'yaml2perl()'." : called and got good result");
is_deeply($perl, $newperl, 'yaml2perl()'." : result is exactly the same as the data structure we started with");
# with unicode
$perl = [
{
"\"ααα'βββ" => "ααα",
"βββ" => 1,
}
];
$yamlstr = perl2yaml($perl);
ok(defined($yamlstr), 'perl2yaml()'." : called and got defined result");
ok($yamlstr =~ /^\-\-\-/, 'perl2yaml()'." : called and looks like a yaml string");
t/14-yaml-tainted-input.t view on Meta::CPAN
];
$yamlstr = perl2yaml($perl);
ok(defined($yamlstr), 'perl2yaml()'." : called and got defined result");
ok($yamlstr =~ /^\-\-\-/, 'perl2yaml()'." : called and looks like a yaml string");
taint($yamlstr);
$newperl = yaml2perl($yamlstr);
ok(defined($newperl), 'yaml2perl()'." : called and got good result with tainted yaml string as input");
is_deeply($perl, $newperl, 'yaml2perl()'." : result is exactly the same as the data structure we started with");
# with unicode
$perl = [
{
"\"ααα'βββ" => "ααα",
"βββ" => 1,
}
];
my $yamlstr2 = perl2yaml($perl);
ok(defined($yamlstr2), 'perl2yaml()'." : called and got defined result");
ok($yamlstr2 =~ /^\-\-\-/, 'perl2yaml()'." : called and looks like a yaml string");
t/20-synopsis.t view on Meta::CPAN
# we are printing to stdout utf8
binmode STDOUT, ':encoding(UTF-8)';
my $jsonstr = '{"Songname": "ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ", "Artist": "ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ"}';
my $yamlstr = Data::Roundtrip::json2yaml($jsonstr);
print $yamlstr."\n";
#---
#Artist: ÎαζανÏÎ¶Î¯Î´Î·Ï Î£ÏÎλιοÏ/ÎίÏÎ²Î¿Ï ÎÏÏÏαÏ
#Songname: ÎÏÏκληÏÎ¿Ï ÏÎ·Ï ÎºÎ¿Î¹Î½ÏνίαÏ
$yamlstr = Data::Roundtrip::json2yaml($jsonstr, {'escape-unicode'=>1});
print $yamlstr."\n";
#---
#Artist: \u039a\u03b1\u03b6\u03b1\u03bd\u03c4\u03b6\u03af\u03b4\u03b7\u03c2 \u03a3\u03c4\u03ad\u03bb\u03b9\u03bf\u03c2/\u0392\u03af\u03c1\u03b2\u03bf\u03c2 \u039a\u03ce\u03c3\u03c4\u03b1\u03c2
#Songname: \u0391\u03c0\u03cc\u03ba\u03bb\u03b7\u03c1\u03bf\u03c2 \u03c4\u03b7\u03c2 \u03ba\u03bf\u03b9\u03bd\u03c9\u03bd\u03af\u03b1\u03c2
# back to json but unescaped unicode chars
my $backtojson = Data::Roundtrip::yaml2json($yamlstr, {'escape-unicode'=>0});
print $backtojson."\n";
# back to json, escape unicode chars
$backtojson = Data::Roundtrip::yaml2json($yamlstr, {'escape-unicode'=>1});
print $backtojson."\n";
$yamlstr = Data::Roundtrip::json2yaml($backtojson, {'escape-unicode'=>0});
print "unescaped yaml:\n".$yamlstr."\n";
$yamlstr = Data::Roundtrip::json2yaml($backtojson, {'escape-unicode'=>1});
print "escaped yaml:\n".$yamlstr."\n";
my $newjson = Data::Roundtrip::yaml2json($yamlstr, {'escape-unicode'=>0});
print "unescaped json:\n".$newjson."\n";
$newjson = Data::Roundtrip::yaml2json($yamlstr, {'escape-unicode'=>1});
print "escaped json:\n".$newjson."\n";
for(1..3){
$newjson = Data::Roundtrip::yaml2json($yamlstr, {'escape-unicode'=>1});
$yamlstr = Data::Roundtrip::json2yaml($newjson, {'escape-unicode'=>1});
}
print "escaped json:\n".$newjson."\n";
print "escaped yaml:\n".$yamlstr."\n";
for(1..3){
$newjson = Data::Roundtrip::yaml2json($yamlstr, {'escape-unicode'=>0});
$yamlstr = Data::Roundtrip::json2yaml($newjson, {'escape-unicode'=>0});
}
print "unescaped json:\n".$newjson."\n";
print "unescaped yaml:\n".$yamlstr."\n";
my $dump = Data::Roundtrip::json2dump($jsonstr,
{'dont-bloody-escape-unicode'=>1}
);
print "unescaped dump:\n".$dump."\n";
$dump = Data::Roundtrip::json2dump($jsonstr,
{'dont-bloody-escape-unicode'=>0}
);
print "escaped dump:\n".$dump."\n";
$dump = Data::Roundtrip::json2dump($jsonstr,
{'dont-bloody-escape-unicode'=>1, 'terse'=>1, 'indent'=>1}
);
print "unescaped, terse dump:\n".$dump."\n";
$dump = Data::Roundtrip::json2dump($jsonstr,
{'dont-bloody-escape-unicode'=>0, 'terse'=>1, 'indent'=>0}
);
print "escaped, terse and with no indentations, dump:\n".$dump."\n";
$backtojson = Data::Roundtrip::dump2json($dump, {'escape-unicode'=>0});
print "unescaped json:\n".$backtojson."\n";
$backtojson = Data::Roundtrip::dump2json($dump, {'escape-unicode'=>1});
print "escaped json:\n".$backtojson."\n";
ok(1==1, "done"); $num_tests++;
done_testing($num_tests);
xt/benchmarks/01-default-unicode-escaping.t view on Meta::CPAN
timethese($num_repeats, {
' /e/d' => \&perl2dump_escape_default,
' /ne/d' => \&perl2dump_no_escape_default,
'f/e/d' => \&perl2dump_filtered_escape_default,
'f/ne/d' => \&perl2dump_filtered_no_escape_default,
'h/e/d' => \&perl2dump_homebrew_escape_default,
'h/ne/d' => \&perl2dump_homebrew_no_escape_default,
}),
);
print "KEY:\n"
." /e/d : perl2dump, escape, 'no-unicode-escape-permanently' not set\n"
." /ne/d : perl2dump, no escape, 'no-unicode-escape-permanently' not set\n"
."f/e/d : perl2dump_filtered, escape, 'no-unicode-escape-permanently' not set\n"
."f/ne/d : perl2dump_filtered, no escape, 'no-unicode-escape-permanently' not set\n"
."h/e/d : perl2dump_homebrew, escape, 'no-unicode-escape-permanently' not set\n"
."h/ne/d : perl2dump_homebrew, no escape, 'no-unicode-escape-permanently' not set\n"
;
plan tests => 1;
pass('benchmark : '.__FILE__);
sub perl2dump_escape_default {
my $x = perl2dump($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_no_escape_default {
my $x = perl2dump($pv, {'dont-bloody-escape-unicode'=>1})
}
sub perl2dump_homebrew_escape_default {
my $x = perl2dump_homebrew($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_homebrew_no_escape_default {
my $x = perl2dump_homebrew($pv, {'dont-bloody-escape-unicode'=>1})
}
sub perl2dump_filtered_escape_default {
my $x = perl2dump_filtered($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_filtered_no_escape_default {
my $x = perl2dump_filtered($pv, {'dont-bloody-escape-unicode'=>1})
}
1;
__END__
xt/benchmarks/02-permanent-no-unicode-escaping.t view on Meta::CPAN
#!perl -T
use 5.008;
use strict;
use warnings;
our $VERSION = '0.29';
use Data::Roundtrip qw/:all no-unicode-escape-permanently/;
use Data::Random::Structure::UTF8;
use Test::More;
use Benchmark qw/timethese cmpthese :hireswallclock/;
my $num_repeats = 50000;
print "$0 : benchmarks...\n";
xt/benchmarks/02-permanent-no-unicode-escaping.t view on Meta::CPAN
timethese($num_repeats, {
' /e/p' => \&perl2dump_escape_permanent,
' /ne/p' => \&perl2dump_no_escape_permanent,
'f/e/p' => \&perl2dump_filtered_escape_permanent,
'f/ne/p' => \&perl2dump_filtered_no_escape_permanent,
'h/e/p' => \&perl2dump_homebrew_escape_permanent,
'h/ne/p' => \&perl2dump_homebrew_no_escape_permanent,
}),
);
print "KEY:\n"
." /e/p : perl2dump, escape, 'no-unicode-escape-permanently' set\n"
." /ne/p : perl2dump, no escape, 'no-unicode-escape-permanently' set\n"
."f/e/p : perl2dump_filtered, escape, 'no-unicode-escape-permanently' set\n"
."f/ne/p : perl2dump_filtered, no escape, 'no-unicode-escape-permanently' set\n"
."h/e/p : perl2dump_homebrew, escape, 'no-unicode-escape-permanently' set\n"
."h/ne/p : perl2dump_homebrew, no escape, 'no-unicode-escape-permanently' set\n"
;
plan tests => 1;
pass('benchmark : '.__FILE__);
sub perl2dump_escape_permanent {
my $x = perl2dump($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_no_escape_permanent {
my $x = perl2dump($pv, {'dont-bloody-escape-unicode'=>1})
}
sub perl2dump_homebrew_escape_permanent {
my $x = perl2dump_homebrew($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_homebrew_no_escape_permanent {
my $x = perl2dump_homebrew($pv, {'dont-bloody-escape-unicode'=>1})
}
sub perl2dump_filtered_escape_permanent {
my $x = perl2dump_filtered($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_filtered_no_escape_permanent {
my $x = perl2dump_filtered($pv, {'dont-bloody-escape-unicode'=>1})
}
1;
__END__
xt/benchmarks/03-permanent-unicode-escaping.t view on Meta::CPAN
#!perl -T
use 5.008;
use strict;
use warnings;
our $VERSION = '0.29';
use Data::Roundtrip qw/:all unicode-escape-permanently/;
use Data::Random::Structure::UTF8;
use Test::More;
use Benchmark qw/timethese cmpthese :hireswallclock/;
my $num_repeats = 50000;
print "$0 : benchmarks...\n";
xt/benchmarks/03-permanent-unicode-escaping.t view on Meta::CPAN
timethese($num_repeats, {
' /e/p' => \&perl2dump_escape_permanent,
' /ne/p' => \&perl2dump_no_escape_permanent,
'f/e/p' => \&perl2dump_filtered_escape_permanent,
'f/ne/p' => \&perl2dump_filtered_no_escape_permanent,
'h/e/p' => \&perl2dump_homebrew_escape_permanent,
'h/ne/p' => \&perl2dump_homebrew_no_escape_permanent,
}),
);
print "KEY:\n"
." /e/p : perl2dump, escape, 'no-unicode-escape-permanently' set\n"
." /ne/p : perl2dump, no escape, 'no-unicode-escape-permanently' set\n"
."f/e/p : perl2dump_filtered, escape, 'no-unicode-escape-permanently' set\n"
."f/ne/p : perl2dump_filtered, no escape, 'no-unicode-escape-permanently' set\n"
."h/e/p : perl2dump_homebrew, escape, 'no-unicode-escape-permanently' set\n"
."h/ne/p : perl2dump_homebrew, no escape, 'no-unicode-escape-permanently' set\n"
;
plan tests => 1;
pass('benchmark : '.__FILE__);
sub perl2dump_escape_permanent {
my $x = perl2dump($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_no_escape_permanent {
my $x = perl2dump($pv, {'dont-bloody-escape-unicode'=>1})
}
sub perl2dump_homebrew_escape_permanent {
my $x = perl2dump_homebrew($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_homebrew_no_escape_permanent {
my $x = perl2dump_homebrew($pv, {'dont-bloody-escape-unicode'=>1})
}
sub perl2dump_filtered_escape_permanent {
my $x = perl2dump_filtered($pv, {'dont-bloody-escape-unicode'=>0})
}
sub perl2dump_filtered_no_escape_permanent {
my $x = perl2dump_filtered($pv, {'dont-bloody-escape-unicode'=>1})
}
1;
__END__