Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl JSON to treat all numbers as string

Tags:

json

perl

In order to create an API that's consistent for strict typing languages, I need to modify all JSON to return quoted strings in place of integers without going through one-by-one and modifying underlying data.

This is how JSON is generated now:

  my $json = JSON->new->allow_nonref->allow_unknown->allow_blessed->utf8;
  $output = $json->encode($hash);

What would be a good way to say, "And quote every scalar within that $hash"?

like image 382
KateYoak Avatar asked Jan 09 '23 11:01

KateYoak


1 Answers

Both of JSON's backends (JSON::PP and JSON::XS) base the output type on the internal storage of the value. The solution is to stringify the non-reference scalars in your data structure.

sub recursive_inplace_stringification {
   my $reftype = ref($_[0]);
   if (!length($reftype)) {
      $_[0] = "$_[0]" if defined($_[0]);
   }
   elsif ($reftype eq 'ARRAY') {
      recursive_inplace_stringification($_) for @{ $_[0] };
   }
   elsif ($reftype eq 'HASH') {
      recursive_inplace_stringification($_) for values %{ $_[0] };
   }
   else {
      die("Unsupported reference to $reftype\n");
   }
}

# Convert numbers to strings.
recursive_inplace_stringification($hash);

# Convert to JSON.
my $json = JSON->new->allow_nonref->utf8->encode($hash);

If you actually need the functionality provided by allow_unknown and allow_blessed, you will need to reimplement it inside of recursive_inplace_stringification (perhaps by copying it from JSON::PP if licensing allows), or you could use the following before calling recursive_inplace_stringification:

# Convert objects to strings.
$hash = JSON->new->allow_nonref->decode(
   JSON->new->allow_nonref->allow_unknown->allow_blessed->encode(
      $hash));
like image 188
ikegami Avatar answered Jan 16 '23 11:01

ikegami