Data-Roundtrip

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

	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ć)

MANIFEST  view on Meta::CPAN

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)

META.json  view on Meta::CPAN

{
   "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",

META.yml  view on Meta::CPAN

---
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'

README  view on Meta::CPAN

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()

README  view on Meta::CPAN


      * :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)

README  view on Meta::CPAN


      * $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

README  view on Meta::CPAN


      * $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:

README  view on Meta::CPAN


      * $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)

README  view on Meta::CPAN

      * $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,

README  view on Meta::CPAN

    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.

README  view on Meta::CPAN

    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)

README  view on Meta::CPAN

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)

README  view on Meta::CPAN

      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>

README.md  view on Meta::CPAN

# 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()`,

README.md  view on Meta::CPAN

- `: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)

README.md  view on Meta::CPAN

- `$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

README.md  view on Meta::CPAN

- `$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:

README.md  view on Meta::CPAN

- `$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`

README.md  view on Meta::CPAN

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,

README.md  view on Meta::CPAN

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.

README.md  view on Meta::CPAN

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)

README.md  view on Meta::CPAN

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)

README.md  view on Meta::CPAN


    [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__



( run in 0.759 second using v1.01-cache-2.11-cpan-88abd93f124 )