Preparing search criteria and results to be e-mailed I'm getting data to fill out an e-mail template, and I'm wondering if this method is too long. How could I refactor it?

sub getEmailData
{
    my $self = shift;

    my $defs = QuickContentFunction::Simple::QuerySearchFieldDefinitions-&gt;new();

    my $phParams = decode_json($self-&gt;parameters);
    my @aFields = split(/~/, $phParams-&gt;{sFields});
    my @aCategories = split(/~/, $phParams-&gt;{sCategories});
    my @aValues = split(/~/, $phParams-&gt;{sValues});
    my @aConditions = split(/~/, $phParams-&gt;{sConditions});

    my $sSummary = $phParams-&gt;{sSummary};
    $sSummary =~ s/\'//g;
    my @aSummary = split(/\d/, $sSummary);

    my $phData = { name =&gt; $self-&gt;name };

    my $mapping = $self-&gt;getOperatorMapping();
    for (my $i = 0; $i &lt; scalar(@aFields); $i++) {
        my $phFieldInfo = $defs-&gt;getFieldHash( $aCategories[$i], $aFields[$i]);

        my $value = $aValues[$i];
        if ($phFieldInfo-&gt;{value_displays}) {
            $value = @{$phFieldInfo-&gt;{value_displays}}[$value];

        } elsif ($phFieldInfo-&gt;{value_keys}) {
            $value = @{$phFieldInfo-&gt;{value_keys}}[$value];
        }

        push( @{$phData-&gt;{conditions}}, {
            field    =&gt; $phFieldInfo-&gt;{field_display},
            operator =&gt; $mapping-&gt;{$phFieldInfo-&gt;{field_type}}-&gt;{$aConditions[$i]},
            value    =&gt; $value,
            postfix  =&gt; $aSummary[$i+1] || undef
        } );
    }

    $phData-&gt;{mode} = lc($phParams-&gt;{sMode});
    if ($self-&gt;hasResults()) {
        $phData-&gt;{deals} = \@{decode_json($self-&gt;result)};
    }

    return $phData;
}
First off, stuff like my @aFields = split(/~/, $phParams-&gt;{sFields}); is a sign of something gone awry. You've just deserialized $phParams from a JSON object, so why isn't this just stored in a normal array?

There is no need to write $i &lt; scalar(@aFields), just write $i &lt; @aFields.

I have some comments wrt. this snippet:

my $value = $aValues[$i];
if ($phFieldInfo-&gt;{value_displays}) {
    $value = @{$phFieldInfo-&gt;{value_displays}}[$value];
} elsif ($phFieldInfo-&gt;{value_keys}) {
    $value = @{$phFieldInfo-&gt;{value_keys}}[$value];
}


You should always use warnings; and use strict;. The above won't run without warnings if warnings are on because @{$phFieldInfo-&gt;{value_keys}}[$value] should be written ${$phFieldInfo-&gt;{value_keys}}[$value].

Also, the whole thing can be written much shorter:

my $value = ${$phFieldInfo-&gt;{value_displays}}[$aValues[$i]]
    || ${$phFieldInfo-&gt;{value_keys}}[$aValues[$i]]
    || $aValues[$i];


Note: this isn't functionally identical with the original code, since I'm assuming that array refs at the keys value_displays and value_keys exists. 

This essentially means "pick the first trueish value". Note that values like undef, 0 or the empty string won't be picked. If you want to be able to pick 0 or the empty string, replace || with //. This requires a recent version of perl (read: not ancient).

The rest looks reasonable. Fixing the stuff I suggested should cut the size a little, and I wouldn't try shortening it further.