=encoding UTF-8

=head1 NAME

JSON::Create - turn a Perl variable into JSON

=head1 SYNOPSIS

    
    use JSON::Create 'create_json';
    my %hash = (a => 'b', c => 'd');
    print create_json (\%hash);
    


produces

    {"a":"b","c":"d"}

=head1 DESCRIPTION

This module produces JSON out of Perl.

The example programs in this documentation are all found in the
directory F<examples/> in the distribution.

=head1 FUNCTIONS

=head2 create_json

    my $json = create_json (\%hash);

Convert a Perl hash reference or array reference into JSON. The return
value is the output JSON.

Details of the conversion of each type are given in
L</CONVERSIONS>. If you want to alter the default conversions, you
need to make an object with L</new>.

=head1 CONVERSIONS

This section details what conversions are applied to the various
inputs to produce outputs.

=head2 Hashes

Associative arrays are converted to JSON objects. The keys are written
into JSON as strings, with any control characters escaped. The order
of the keys is as they are supplied by Perl.

    
    use JSON::Create 'create_json';
    my %example = (
        down => {
            and => {
                down => {
                    and => {
                        down => {
                            and => {
                                down => 'we go'
                            }
                        }
                    }
                }
            }
        },
    );
    print create_json (\%example);


outputs

    {"down":{"and":{"down":{"and":{"down":{"and":{"down":"we go"}}}}}}}

=head2 Arrays

Arrays are converted to JSON arrays. The order of the array is
identical to the Perl one.

    
    use utf8;
    use JSON::Create 'create_json';
    my @array = (1, 2, 2.5, 'Acme', 
             {
                 cats => [qw/mocha dusty milky/], 
                 dogs => [qw/Tico Rocky Pinky/],
             });
    print create_json (\@array);


outputs

    [1,2,2.5,"Acme",{"cats":["mocha","dusty","milky"],"dogs":["Tico","Rocky","Pinky"]}]

=head2 Scalars

Non-reference scalars are converted to strings, JSON integers or JSON
floats depending on what Perl says they contain.

=head3 Strings

As far as possible, strings are written as-is to the JSON.  See
L</RFC 7159> for details of JSON's rules for strings.

Bytes of value less than 0x20 are converted into the appropriate JSON
escapes, either the whitespace escapes \b (backspace) \r, \t, \n, and
\f, or the form \u0001 for other control characters. The backslash is
written as \\ and double quotes are written as \". 

    
    use JSON::Create 'create_json';
    my $weirdstring = {weird => "\t\r\n\x00"};
    print create_json ($weirdstring);
    


outputs

    {"weird":"\t\r\n\u0000"}

By default, the forward slash, /, known as "solidus" in the JSON
specification, is not escaped. If you need to escape forward slashes,
create a JSON::Create object with L</new>, set it to escape slashes
with L</escape_slash>, then create the JSON with L</run> rather than
L</create_json>.

Unicode values are not escaped.

=head3 Integers

Integers are printed in the obvious way. Note that what you input to
Perl as an integer, Perl may interpret to be a floating point number,
if has a very large absolute value, in which case this module will
print it out like a floating point number.

=head3 Floating point numbers

Finite floating point numbers are printed using printf formatting via
C<"%g">. You can alter the format used to print floating point numbers
by creating an object with L</new>, setting the format with
L</set_fformat>, and creating the json with L</run> rather than
L</create_json>.

NaN (not a number) is converted to the string C<"nan">, the letters
C<nan> surrounded by double quotes. Similarly, positive and negative
infinity are converted to the strings C<"inf"> and C<"-inf">
respectively. Note that JSON does not allow NaN or infinity as bare
values. From page 6 of L</RFC 7159>:

    Numeric values that cannot be represented in the grammar below
    (such as Infinity and NaN) are not permitted.

=head3 The undefined value

Undefined values are mapped to the JSON literal "null".

=head3 Booleans

Booleans (C<true> and C<false>) from input via JSON::Parse (version
0.36_01 or later) will be turned into C<true> and C<false>
outputs. You can also arrange for Perl objects, such as the "true" and
"false" values of L<JSON::PP>, to be converted to booleans using
L</bool>. This requires the use of a JSON::Create object created via
L</new>.

=head3 Unicode escapes

There is no facility to produce Unicode escapes of the form C<\u3000>,
except for control characters (bytes less than 0x20 in value which are
not whitespace or \b).

=head3 Unicode

If any part of the input object is marked as "utf8" (multibyte
characters), every non-ASCII string in the input object needs to be
marked as such, otherwise the module prints a warning and returns an
undefined value. If every part of the input is not marked as "utf8",
this does not happen, but there is also currently no validation of the
output as being in Unicode, so binary strings can pass through without
correction. See also L</BUGS>.

=head2 Other reference types

=head3 Regexes

If the scalar contains a regex then JSON::Create lets Perl convert the
regex to a string then adds that. The output depends on the Perl
version.

=head3 Code references and other

A code reference in the input causes the entire return value to be the
undefined value.

=head1 METHODS

If you want to alter the format of the output from the default, it's
necessary to create an object and then set the defaults on that
object.

=head2 new

    my $jc = JSON::Create->new ();

Create a new "JSON::Create" object. You need to use L</run> to
generate JSON with this.

=head2 run

    my $json = $jc->run ($input);

This does exactly the same thing as L</create_json>, unless you have
altered the output format. The return value is the output JSON.

=head2 Methods for formatting the output

These methods work on the object created with L</new> to format the
output JSON in a different way from the default.

=head3 bool

    $jc->bool ('boolean');

Given a list of object types, it will convert objects of these types
into the JSON literals C<true> or C<false> depending on whether Perl
thinks they're true or false. (This interface is experimental, and may
change without notice.)

    
    use JSON::Create;
    use boolean;
    my $thing = {'Yes' => true, 'No' => false};
    my $jc = JSON::Create->new ();
    print $jc->run ($thing), "\n";
    $jc->bool ('boolean');
    print $jc->run ($thing), "\n";
    


outputs

    {"No":"0","Yes":"1"}
    {"No":false,"Yes":true}


=head4 Interoperability

The boolean values of the following Perl modules can interoperate with
JSON::Create. 

=over

=item L<boolean>

    $jc->bool ('boolean');

=item L<JSON::Tiny>

    $jc->bool ('JSON::Tiny::_Bool');

Round trip compatibility is also confirmed for JSON::Tiny version 0.54.

=item L<JSON::PP>

    $jc->bool ('JSON::PP::Boolean');

Round trip compatibility is also confirmed for JSON::PP version 2.27300.

=item L<Types::Serialiser>

    $jc->bool ('JSON::PP::Boolean');

B<Please note> the above is not a typo, L<JSON::PP::Boolean> is the
correct object type for Types::Serialiser. To confirm this, try

    print ref $Types::Serialiser::false;

=item L<Mojo::JSON>

    $jc->bool ('JSON::PP::Boolean', 'Mojo::JSON::_Bool');

Round trip compatibility is also confirmed for Mojo::JSON version 6.25.

The current version of Mojo::JSON (Mojolicious version 6.25) actually
depends on L<JSON::PP> and uses the type C<JSON::PP::Boolean> for its
true and false values. Older versions used their own type,
C<Mojo::JSON::_Bool>.

JSON::Create's tests for Mojo::JSON compatibility are currently
commented out by default, because different versions of Mojolicious
differ a lot in not only function names but also variable names, as
seen above. If you want to run these tests, please edit the file
F<t/bool.t> in the distribution.

=back

You can also switch on multiple modules using a list:

    $jc->bool (qw/boolean JSON::Tiny::_Bool JSON::PP::Boolean/);

The compatibility of the above modules can be confirmed by running the
test script F<t/bool.t> in the distribution. However, JSON::Create
does not install these modules, so unless you have installed them
yourself, the tests will just be skipped.

More modules will be added to this list as time permits.

=head3 escape_slash

    $jc->escape_slash (1);

Call this with a true value to make the slash (known as the "solidus"
in the JSON specification) be escaped with a backslash. Call this with
any false value to make the slash not be escaped (the default
behaviour).

    
    use JSON::Create;
    my $jc = JSON::Create->new ();
    my $in = {'/dog/' => '/run/'};
    print $jc->run ($in), "\n";
    $jc->escape_slash (1);
    print $jc->run ($in), "\n";
    $jc->escape_slash (0);
    print $jc->run ($in), "\n";


outputs

    {"/dog/":"/run/"}
    {"\/dog\/":"\/run\/"}
    {"/dog/":"/run/"}


=head3 obj

    $jc->obj ('Zilog::Z80' => sub { my ($obj) = @_; print "\"Z80\""; });

With this method you can register JSON generators for your Perl
objects. When JSON::Create finds your object, it will call the method
you have supplied.

Call C<obj> with a hash. The keys are your object names, and the
corresponding values are code references to the function you want to run:

    $jc->obj (
         'My::Cool::Object' => \& object_to_json,
    );

The function is called with the object reference as its only
argument, as if called like this:

    my $user_json = $cool_object->object_to_json ();

The return value of your function, C<object_to_json> in the above
example, must be a single value, a string containing your object's
JSON encoding.

    
    use JSON::Create;
    my $jc = JSON::Create->new ();
    package Zilog::Z80;
    sub new { return bless { memory => '64 kbytes' }; }
    sub to_json {
        my ($self) = @_;
        return '"I can address as many as '.$self->{memory}.' of memory"';
    }
    1;
    package main;
    my $zilog = Zilog::Z80->new ();
    my %stuff = (zilog => $zilog);
    print $jc->run (\%stuff), "\n";
    # Set up our object's method for printing JSON.
    $jc->obj (
        'Zilog::Z80' => \& Zilog::Z80::to_json,
    );
    print $jc->run (\%stuff), "\n";


produces

    {"zilog":{"memory":"64 kbytes"}}
    {"zilog":"I can address as many as 64 kbytes of memory"}


The output of your method is passed through to the output string
completely unaltered. If you want to have your JSON output checked for
validity, you can switch on validation using the method L</validate>.

=head3 set_fformat

    $jc->set_fformat ('%e');

This sets the printf-style format string used to print floating point
numbers. This is validated and a warning printed if the format cannot
be used. The format is also restricted to a maximum length to prevent
buffer overflows within the module.

    
    use JSON::Create;
    my $jc = JSON::Create->new ();
    my @array = (1000000000.0,3.141592653589793238462643383279502884197169399375105820974944592307816406,0.000000001);
    print $jc->run (\@array), "\n";
    $jc->set_fformat ('%.3f');
    print $jc->run (\@array), "\n";
    $jc->set_fformat ('%E');
    print $jc->run (\@array), "\n";
    $jc->set_fformat ();
    print $jc->run (\@array), "\n";


outputs

    [1e+09,3.14159,1e-09]
    [1000000000.000,3.142,0.000]
    [1.000000E+09,3.141593E+00,1.000000E-09]
    [1e+09,3.14159,1e-09]


=head3 unicode_escape_all

Call this with a true value to make all Unicode characters be escaped
into the \u3000 format. (Not implemented yet, see L</BUGS>.)

=head3 unicode_upper

    $jc->unicode_upper (1);

Call this with a true value to make Unicode escapes use upper case
hexadecimal. Call this with a false value to revert to the default
behaviour. This isn't tested yet, because the Unicode validation is
not yet implemented, see L</BUGS>.

=head3 validate

    $jc->validate (1);

If this is called with a true value, validate the user-generated JSON
given by the callbacks registered with L</obj>. The validation is done
via the routine C<assert_valid_json> of L<JSON::Parse>, so you need to
have that module installed to use this.

If JSON::Parse is installed, and the JSON fails to validate, this will
produce a fatal error. If JSON::Parse is not installed, it will also
produce a fatal error, regardless of whether your JSON is valid.

=head1 EXPORTS

The module exports nothing except by request. One function,
L</create_json>, is exported on request.

=head1 INSTALLATION

The module uses C internally, so you need a C compiler to install
it. There is also an undocumented "pure Perl" module JSON::Create::PP
in the distribution, which could be used in a pinch. (This is
basically a reference module though.)

=head1 SEE ALSO

=over

=item RFC 7159

JSON is specified in L<RFC 7159 "The application/json Media Type for
JavaScript Object Notation
(JSON)"|http://www.ietf.org/rfc/rfc7159.txt>.

=item json.org

L<http://json.org> is the website for JSON, authored by Douglas
Crockford.

=item JSON::Parse

This module is a companion module to the same author's
L<JSON::Parse>. Please see that module's documentation for links to
the JSON standard itself, a summary of the ever-growing list of JSON
modules on CPAN (under "SEE ALSO") and the reasons why I decided to
write these two modules (under "HISTORY").

=back

=head1 BUGS

The planned Unicode support (byte-by-byte checking) is not yet fully
implemented. For example, JSON is required to be in Unicode, but it's
possible to pass non-Unicode strings through this module by switching
off the Perl UTF-8 flag everywhere, since unmarked binary bytes are
currently not validated independent of Perl's validation, which does
not apply to unmarked strings. Also, full escaping and escaping of
C<\u2028> and C<\u2029> are not implemented yet.

There is currently no facility to add whitespace to the output JSON.

There is currently no way to delete object handlers from a
JSON::Create object.

=head1 PERFORMANCE

This module is currently at an early stage of development, so speed is
not a key issue until the module is demonstrably producing correct
outputs.

However, due to user interest, there is a benchmarking script in
F<bench/bench.pl> which compares the performance of the module with
L<JSON::XS> and L<Cpanel::JSON::XS>. Outputs look like this:

    Versions used:
    
    CJX	Cpanel::JSON::XS	3.0115
    JX	JSON::XS	3.01
    JC	JSON::Create	0.07
    
    Comparing hash of ASCII strings...
    
          Rate  CJX   JX   JC
    CJX 41.3/s   --  -2% -35%
    JX  42.0/s   2%   -- -34%
    JC  63.7/s  54%  52%   --
    
    Comparing hash of integers...
    
          Rate  CJX   JX   JC
    CJX 16.1/s   --  -2% -58%
    JX  16.3/s   2%   -- -57%
    JC  38.3/s 138% 135%   --
    
    Comparing hash of Unicode strings...
    
          Rate  CJX   JX   JC
    CJX 47.8/s   --  -4% -47%
    JX  50.0/s   5%   -- -44%
    JC  89.5/s  87%  79%   --
    
    Comparing array of floats...
    
          Rate   JX  CJX   JC
    JX  14.1/s   --  -0% -60%
    CJX 14.1/s   0%   -- -60%
    JC  35.5/s 152% 151%   --


This only compares a few simple cases in which the output is
demonstrably correct. Also, at least on my computer, the numbers seem
to vary wildly from one test to another.

=head1 HISTORY

I started making this module so that, with this and L<JSON::Parse>, I
wouldn't have to use the existing JSON modules on CPAN. See the
HISTORY section of the documentation of L<JSON::Parse> for full
details.

The exact time I've spent making this module is recorded in the file
F<timesheet.txt> in the top directory of the distribution. At the time
of version 0.07, I've spent 1 day, 2 hours and 26 minutes working on
this.

The module is currently in use everywhere that I need to generate JSON
within Perl. However, I would suggest caution in switching to this
module from the more established JSON solutions on CPAN, since not all
parts are implemented yet.


=head1 AUTHOR

Ben Bullock, <bkb@cpan.org>

=head1 COPYRIGHT & LICENCE

This package and associated files are copyright (C) 
2015
Ben Bullock.

You can use, copy, modify and redistribute this package and associated
files under the Perl Artistic Licence or the GNU General Public
Licence.


=head1 TERMINOLOGY

This defines the terminology used in this document.

=over

=item Convenience function

In this document, a "convenience function" indicates a function which
solves some of the problems, some of the time, for some of the people,
but which may not be good enough for all envisaged uses. A convenience
function is an 80/20 solution, something which solves (about) 80% of
the problems with 20% of the effort. Something which does the obvious
things, but may not do all the things you might want, a time-saver for
the most basic usage cases.

=item BUGS

In this document, the section BUGS describes possible deficiencies,
problems, and workarounds with the module. It's not a guide to bug
reporting, or even a list of actual bugs. The name "BUGS" is the
traditional name for this sort of section in a Unix manual page.

=back



=cut

