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: TellsJSONto call theTO_JSONmethod 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_JSONmust not produce blessed refs. - TMTOWTDI (There’s more than one way to do it): Some use
encode_json, some preferJSON->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:
Personis a class withnewand aTO_JSONmethod.- When
encodeis called on the$personinstance,convert_blessed(1)causesTO_JSONto be called, returning a plain hashref representing selected data and a customage_category. - The output JSON includes keys
name,age, and the computedage_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 asnull. - 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_JSONif objects contain other objects. - Context confusion:
TO_JSONruns 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
Serialized JSON:
{
"name" : "Alice",
"age_category" : "adult",
"age" : 30
}
Decoded name: Alice
Decoded age category: adult
(empty)