CropCircle has asked for the wisdom of the Perl Monks concerning the following question:

Hello! I have a variable ($json), which contains some json structure, then try to write it in data_out file but get this error: malformed text data., at character offset 0 (before "HASH(0x39e290)"). Here is the code:

use strict; use warnings; binmode STDOUT, ":utf8"; use utf8; use JSON; my $json ={ 'book' => { 'title' => 'smth', 'num_page' => 234 } }; my $data = decode_json($json); open my $fh, ">", "data_out.json"; print $fh encode_json($data); close $fh;

Have no ideas how to fix it. Thanks for help!

Replies are listed 'Best First'.
Re: Write json structure to a file
by Corion (Patriarch) on Aug 13, 2015 at 11:29 UTC

    Your initial data structure in $json is a data structure and not text. So it does not make sense to call decode_json with it. Just delete that line.

      It works now but I get data_out file with wrong order of structure fields - the first field is num_page, not title. Is it possible to make it constant?

        No. Perl hashes have no order, so the sequence in which hash keys are serialized is more or less random.

        Update: Note that Javascript does not define an order over the properties of objects either, so there is very little guarantee that a JSON document will have the keys in a specific order. It seems that ECMAscript 6 standardizes somewhat on "insertion order".

        The JSON definition declares that

        An object is an unordered set of name/value pairs.

        So, for hashes, JSON does not specify an order of the keys.

        If you wish it to be ordered in your output (more for human consumption), look at the JSON Documentation at the canonical option.

        Update: fixed link (Your Mother)

        --MidLifeXis

        ++Corion, and so if you want ordered pairs (same rules for json as Perl), the most obvious treatment is to replace that hash with an array of little hashes, e.g.:
        use strict; use warnings; binmode STDOUT, ":utf8"; use utf8; use JSON; my $json ={ 'book' => [ {'title' => 'smth'}, {'num_page' => 234} ] }; open my $fh, ">", "data_out.json"; print $fh encode_json($json); close $fh;
        Alternatively, you could sort the hash keys on the receiving end in Javascript into a particular order (put the key names in another hash with the sort positions as values for use in a sort function in Javascript) but that would be outside the scope of the monastery.

        One world, one people