http intermediate

How to send JSON data in POST request with LWP::UserAgent?

Question

How to send JSON data in POST request with LWP::UserAgent?

Sending JSON Data in a POST Request with LWP::UserAgent

When working with HTTP APIs in Perl, LWP::UserAgent is one of the go-to modules for making web requests. Sending JSON data in a POST request is a common task, typically required when interacting with RESTful APIs. This involves two key steps:

  • Encoding your data structure into JSON format.
  • Setting the proper Content-Type header to application/json.

Perl’s JSON module makes encoding data to JSON straightforward. We then set the POST content to the JSON string and specify the correct content type, so the server knows how to interpret the payload.

Key Concepts

  • Sigils: Scalars ($) hold JSON strings; references (e.g., hashes or arrays) are encoded.
  • Context: JSON encoding expects normal Perl data structures (hashrefs, arrayrefs).
  • TMTOWTDI: There are multiple JSON modules (like JSON::XS, JSON::PP), but the core JSON module is often sufficient.

Note: LWP::UserAgent->post() can take parameters either as a form or as raw content. For JSON, you must use the raw content approach.

Example: Sending JSON POST with LWP::UserAgent

#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use JSON;

# Create a user agent object
my $ua = LWP::UserAgent->new;

# Define a Perl data structure to encode as JSON
my $data = {
    name => "Alice",
    age  => 30,
    interests => ['Perl', 'Web APIs', 'JSON']
};

# Encode data structure to JSON string
my $json = encode_json($data);

# Set the target URL (example placeholder)
my $url = 'http://httpbin.org/post';

# Make the POST request with JSON content and proper header
my $response = $ua->post(
    $url,
    'Content-Type' => 'application/json',
    Content        => $json,
);

# Check the response and print content or error
if ($response->is_success) {
    print "Response received:\n";
    print $response->decoded_content;
} else {
    warn "HTTP POST failed: ", $response->status_line, "\n";
}

Explanation

  • encode_json($data) converts the Perl hashref into a JSON string.
  • The Content-Type header explicitly tells the server the payload is JSON.
  • Content => $json sends the raw JSON string as the POST body.
  • http://httpbin.org/post is a great testing endpoint that echoes back your POST data.

Common Gotchas

  • Using the POST $url, \%form form submits content as application/x-www-form-urlencoded, not JSON.
  • For older Perl versions, ensure JSON module is installed (core from Perl 5.14+).
  • Remember to handle UTF-8 encoding if your data contains Unicode characters; encode_json takes care of UTF-8 encoding internally.
  • Always check $response->is_success before trusting the response content.

This approach works for Perl 5.10 and later with the standard core modules. For advanced use cases, modules like HTTP::Tiny or Mojo::UserAgent also support JSON POSTs but LWP::UserAgent remains widely used for backward compatibility.

Verified Code

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

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Response received:
{
  "args": {}, 
  "data": "{\"interests\":[\"Perl\",\"Web APIs\",\"JSON\"],\"age\":30,\"name\":\"Alice\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "64", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "libwww-perl/6.44", 
    "X-Amzn-Trace-Id": "Root=1-69534e87-0363109327ef8dc46f9a49eb"
  }, 
  "json": {
    "age": 30, 
    "interests": [
      "Perl", 
      "Web APIs", 
      "JSON"
    ], 
    "name": "Alice"
  }, 
  "origin": "107.167.18.100", 
  "url": "http://httpbin.org/post"
}
STDERR
(empty)

Was this helpful?

Related Questions