How to serialize Perl objects to JSON with custom encoding?

Question

How to serialize Perl objects to JSON with custom encoding?

How to Serialize Perl Objects to JSON with Custom Encoding

Serializing Perl objects to JSON requires converting the blessed references (objects) into a representation that JSON understands—usually a hash or array of data. Since Perl’s JSON module (from CPAN, part of core since Perl 5.14+) doesn’t automatically know how to encode objects, you need to provide custom encoding logic for your classes.

The common approach is using the convert_blessed option in JSON combined with a TO_JSON method in your object's package. The TO_JSON method returns a data structure suitable for JSON encoding, letting you define exactly how your object's data is serialized.

Key Concepts

  • convert_blessed: Tells JSON to call the TO_JSON method on blessed objects.
  • TO_JSON: A method you define in your class that returns a pure data structure (hash/array) ready for JSON encoding.
  • Sigils and references: Remember to use the correct dereferencing syntax. Objects in Perl are blessed refs, often hashes or arrays.
  • Context: JSON encoding happens in scalar context, the TO_JSON must not produce blessed refs.
  • TMTOWTDI (There’s more than one way to do it): Some use encode_json, some prefer JSON->new. Both valid; here we show the OO approach.

Example: Custom Object Serialization


use strict;
use warnings;
use JSON;

# Example class representing a simple Person object
package Person;

sub new {
    my ($class, %args) = @_;
    return bless \%args, $class;
}

# TO_JSON defines how to serialize this object to JSON.
# It returns a plain hashref (no blessing)
sub TO_JSON {
    my ($self) = @_;
    # Customize what keys to expose and any transformations
    return {
        name => $self->{name},
        age  => $self->{age},
        # Add custom encoding, e.g., age category instead of raw age
        age_category => $self->{age} < 18 ? "child" : "adult",
    };
}

package main;

# Create person object
my $person = Person->new(name => "Alice", age => 30);

# Create JSON encoder with convert_blessed enabled
my $json = JSON->new->utf8->pretty->convert_blessed(1);

# Encode the object
my $json_text = $json->encode($person);

print "Serialized JSON:\n$json_text\n";

# Decoding back to Perl hashref as an example
my $data = $json->decode($json_text);
print "Decoded name: $data->{name}\n";
print "Decoded age category: $data->{age_category}\n";

Explanation

In this example:

  • Person is a class with new and a TO_JSON method.
  • When encode is called on the $person instance, convert_blessed(1) causes TO_JSON to be called, returning a plain hashref representing selected data and a custom age_category.
  • The output JSON includes keys name, age, and the computed age_category.
  • This separates data representation from object internals, which might have other metadata you don’t want to serialize.

Common Pitfalls

  • Forgetting convert_blessed(1): Without this, objects cause an error or encode as null.
  • Returning blessed refs from TO_JSON: Always return plain data refs so JSON serializes cleanly.
  • Modifying internal object state inside TO_JSON: Keep serialization side-effect free.
  • Not handling nested objects: You may need nested TO_JSON if objects contain other objects.
  • Context confusion: TO_JSON runs in scalar context; returning array refs or scalars directly can cause errors.

Summary

Using convert_blessed and defining TO_JSON in your classes is the idiomatic way to serialize Perl objects to JSON with full control over encoding. It leverages Perl’s flexibility and the JSON module’s hooks to produce clean, custom JSON output representing your object data exactly as you need.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 25ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Serialized JSON:
{
   "name" : "Alice",
   "age_category" : "adult",
   "age" : 30
}

Decoded name: Alice
Decoded age category: adult
STDERR
(empty)

Was this helpful?

Related Questions