How to POST a JSON data using cURL

May 19, 2022 No comments curl JSON POST

1. Introduction

The curl is a free and open-source command-line tool for transferring data using many protocols such as HTTP, SFTP, SMTP, TELNET, and more. This software is very popular among developers and DevOps around the world. In this article, we will focus on how to POST JSON data using curl.

2. POST JSON data with curl on Linux

To send JSON data that will be properly parsed on the server-side, using curl, we need to add the Content-Type header with application/json value to our request.

We can do it using -H or --header parameter, according to the document curl-H:

-H, --header <header/@file>

(HTTP) Extra header to include in the request when sending HTTP to a server. 
You may specify any number of extra headers. Note that if you should add a 
custom header that has the same name as one of the internal ones curl would 
use, your externally set header will be used instead of the internal one. This 
allows you to make even trickier stuff than curl would normally do. You should
not replace internally set headers without knowing perfectly well what you are
doing. Remove an internal header by giving a replacement without content on the
right side of the colon, as in: -H "Host:". If you send the custom header with
no-value then its header must be terminated with a semicolon, such as
-H "X-Custom-Header;" to send "X-Custom-Header:".

In our case we need to set application/json header, to do so we will use the following parameter:

-H "Content-Type: application/json"

The example curl command that POST JSON data could look as follows:

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"firstName":"John","lastName":"Doe"}' \
  http://localhost:8080/api/customer

In that example we used parameters such as:

  • --request POST - that is optional, because -d or --data parameters implies a POST request,
  • --data '[json]' - parameter with JSON data we want to send,
  • http://localhost:8080/api/customer - this is an URL where we want to sent prepared JSON.

2. POST JSON data with curl on Windows

Things are a little bit different on the Windows OS. For windows, single quotes around JSON data didn't work correctly.

So, we should not use a single quote at all, and double quotes should be escaped like in the following example:

curl --header "Content-Type: application/json" \
  --request POST \
  --data "{\"firstName\":\"John\",\"lastName\":\"Doe\"}" \
  http://localhost:8080/api/customer

3. POST JSON data from a file using curl

In case you want to POST a JSON from a file, you will need to use the @ parameter with the name of that file.

Let's check the example command:

curl --header "Content-Type: application/json" \
  --request POST \
  --data-binary @sample-file.json \
  http://localhost:8080/api/customer

Note that in this example we used --data-binary instead of --data param. That param indicates that data will be sent as-is. The --data parameter strips CR and LF from the input.

4. Post JSON using special --json option

The --json parameter works as a shortcut for passing on these three options:

  • --data [arg]
  • --header "Content-Type: application/json"
  • --header "Accept: application/json"

This is a new option introduced by cURL in version 7.82.0.

With --json parameter we could simplify our command into:

curl --json '{"firstName":"John","lastName":"Doe"}' http://localhost:8080/api/customer

5. Test sending JSON data with curl

To test if POST requests generated by curl are correct we will use a spring-boot application with a simple REST API.

Application is configured to print all requests with headers, query parameters, etc.

package com.frontbackend.springboot.curl;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.filter.CommonsRequestLoggingFilter;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommonsRequestLoggingFilter requestLoggingFilter() {
        CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
        loggingFilter.setIncludeClientInfo(true);
        loggingFilter.setIncludeQueryString(true);
        loggingFilter.setIncludePayload(false);
        loggingFilter.setIncludeHeaders(true);
        loggingFilter.setAfterMessagePrefix("REQUEST DATA : ");
        return loggingFilter;
    }
}

The CurlController is responsible for handing all requests to our server:

package com.frontbackend.springboot.curl.controller;

import com.frontbackend.springboot.curl.model.Customer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class CurlController {

    @RequestMapping("/log/body/json")
    public void logBodyJSON(@RequestBody Customer customer) {
        log.info("Customer from Payload = {}", customer);
    }
}

The Customer with Address will be our testing objects, on which we will check if POST requests with JSON data are correct, and spring-boot can parse it.

package com.frontbackend.springboot.curl.model;

import java.util.List;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Setter
@Getter
@NoArgsConstructor
@ToString
public class Customer {

    private String firstName;
    private String lastName;
    private List<Address> addressList;
}
package com.frontbackend.springboot.curl.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Setter
@Getter
@NoArgsConstructor
@ToString
public class Address {

    private String city;
    private String street;
    private String country;
    private String state;
}
5.1. POST Customer data in JSON to the Spring Boot application server

Let's POST a JSON data with Customer information:

curl --request POST 'http://localhost:8080/log/body/json' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName": "John",
    "lastName": "Doe",
    "addressList": [
        {
            "city": "South Haleigh",
            "street": "83362 Fay Inlet",
            "state": "Rhode Island",
            "country": "US"
        },
        {
            "city": "Deionport",
            "street": "940 Kertzmann Garden",
            "state": "Arkansas",
            "country": "US"
        }
    ]
}'

Server logs the following output on the console:

2022-05-15 00:09:46.623 DEBUG 113457 --- [nio-8080-exec-1] o.s.w.f.CommonsRequestLoggingFilter      : Before request [POST /log/body/json, client=127.0.0.1, headers=[host:"localhost:8080", user-agent:"curl/7.68.0", accept:"*/*", content-length:"402", Content-Type:"application/json;charset=UTF-8"]]
2022-05-15 00:09:46.623  INFO 113457 --- [nio-8080-exec-1] c.f.s.curl.controller.CurlController     : Customer from Payload = Customer(firstName=John, lastName=Doe, addressList=[Address(city=South Haleigh, street=83362 Fay Inlet, country=US, state=Rhode Island), Address(city=Deionport, street=940 Kertzmann Garden, country=US, state=Arkansas)])
2022-05-15 00:09:46.624 DEBUG 113457 --- [nio-8080-exec-1] o.s.w.f.CommonsRequestLoggingFilter      : REQUEST DATA : POST /log/body/json, client=127.0.0.1, headers=[host:"localhost:8080", user-agent:"curl/7.68.0", accept:"*/*", content-length:"402", Content-Type:"application/json;charset=UTF-8"]]

As you can see Spring Boot property parse input JSON and create an instance of the Customer object with the Address list.

5.2. Post JSON data from a file

Let's create a sample-file.json file with the following content:

{
    "firstName": "John",
    "lastName": "Doe"
}

To POST data from that file we will use the following command:

curl --header "Content-Type: application/json" \
  --request POST \
  --data-binary @sample-file.json \
  http://localhost:8080/log/body/json

Server output is as follows:

2022-05-15 00:15:48.108 DEBUG 113457 --- [nio-8080-exec-7] o.s.w.f.CommonsRequestLoggingFilter      : Before request [POST /log/body/json, client=127.0.0.1, headers=[host:"localhost:8080", user-agent:"curl/7.68.0", accept:"*/*", content-length:"51", Content-Type:"application/json;charset=UTF-8"]]
2022-05-15 00:15:48.109  INFO 113457 --- [nio-8080-exec-7] c.f.s.curl.controller.CurlController     : Customer from Payload = Customer(firstName=John, lastName=Doe, addressList=null)
2022-05-15 00:15:48.109 DEBUG 113457 --- [nio-8080-exec-7] o.s.w.f.CommonsRequestLoggingFilter      : REQUEST DATA : POST /log/body/json, client=127.0.0.1, headers=[host:"localhost:8080", user-agent:"curl/7.68.0", accept:"*/*", content-length:"51", Content-Type:"application/json;charset=UTF-8"]]

6. Conclusion

In this article, we focused on preparing the correct POST command using curl that will send JSON data to a Spring Boot server.

The code used on the server-side is available under GitHub repository.

{{ message }}

{{ 'Comments are closed.' | trans }}