Himanshu SharmaSoftware engineer
Let’s talk

jQuery · Lesson 36 of 45

Sending data: POST, forms and JSON

Send data to a server with jQuery $.post() and $.ajax(), submit forms with .serialize(), send JSON bodies, upload files with FormData, and use PUT and DELETE.

13 minAjaxUpdated 23 October 2026

By the end of this lessonSend form fields, JSON and files to an API with the right method and content type, and update the page from the server's reply.

Posting form-style data

$.post(url, data, callback) sends a POST request. By default the data is encoded the same way a normal HTML form encodes it (application/x-www-form-urlencoded), which every server framework understands:

html
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $.post("https://jsonplaceholder.typicode.com/posts", { title: "My first post", body: "Hello", userId: 1 })
    .done(function (created) {
      console.log("created with id", created.id);
      console.log("title:", created.title, "| userId:", created.userId);
    });
</script>
result
created with id 101
title: My first post | userId: 1

JSONPlaceholder pretends to save the post and returns it with a new id of 101. It does not really store anything, so the same request always gives the same answer, which makes it good for learning.

Sending a whole form

.serialize() reads every field in a form and builds that encoded string for you:

html
<form id="comment-form">
  <input name="name" value="Asha Verma">
  <input name="email" value="asha@example.com">
  <textarea name="body">Great lesson & clear examples</textarea>
  <label><input type="checkbox" name="subscribe" value="yes" checked> Subscribe</label>
  <input name="secret" value="x" disabled>
  <button>Post comment</button>
</form>
<p id="status"></p>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#comment-form").on("submit", function (event) {
    event.preventDefault();
    const payload = $(this).serialize();
    console.log("sending:", payload);

    $.post("https://jsonplaceholder.typicode.com/comments", payload)
      .done(function (saved) {
        $("#status").text("Thanks, " + saved.name + "! Comment #" + saved.id + " posted.");
        console.log("saved id:", saved.id, "| subscribe:", saved.subscribe);
      });
  });
</script>
result
sending: name=Asha%20Verma&email=asha%40example.com&body=Great%20lesson%20%26%20clear%20examples&subscribe=yes
saved id: 501 | subscribe: yes

.serialize() follows the same rules as a real form submission: only fields with a name, not disabled, and only ticked checkboxes and radios. The & in the comment was encoded as %26 so it cannot break the format. .serializeArray() gives the same fields as an array of { name, value } objects if you need to inspect or change them first.

Sending JSON

Many modern APIs expect a JSON body instead. Set contentType to say what you are sending, and convert the data to a JSON string yourself:

html
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  const order = { customer: "Ravi", items: [{ sku: "LAMP-1", qty: 2 }], gift: false };

  $.ajax({
    url: "https://jsonplaceholder.typicode.com/posts",
    method: "POST",
    contentType: "application/json",
    data: JSON.stringify(order),
    dataType: "json"
  }).done(function (saved) {
    console.log("id:", saved.id, "| items:", saved.items.length, "| first sku:", saved.items[0].sku, "| gift:", saved.gift);
  });
</script>
result
id: 101 | items: 1 | first sku: LAMP-1 | gift: false

Notice the three settings working together:

  • contentType: "application/json" describes the request body;
  • data: JSON.stringify(order) is that body, as a string (without stringify, jQuery would form-encode the object);
  • dataType: "json" describes the response.

JSON keeps types and nesting: the server received gift as a real false and items as an array, which form encoding cannot express directly.

PUT, PATCH and DELETE

REST APIs use different methods for different actions: PUT replaces a resource, PATCH changes part of it, DELETE removes it. Set method in $.ajax():

html
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  const base = "https://jsonplaceholder.typicode.com/posts/1";

  $.ajax({ url: base, method: "PATCH", contentType: "application/json", data: JSON.stringify({ title: "Updated title" }) })
    .then(function (post) {
      console.log("PATCH:", post.id, post.title);
      return $.ajax({ url: base, method: "DELETE" });
    })
    .then(function (result, status, xhr) {
      console.log("DELETE status:", xhr.status, "| body:", JSON.stringify(result));
    });
</script>
result
PATCH: 1 Updated title
DELETE status: 200 | body: {}

Returning the second request from the first .then() makes them run one after the other: the delete starts only after the update has finished. The Deferreds lesson explains this chaining.

Uploading files

.serialize() cannot include files. Use the browser's FormData object, and tell jQuery not to process it:

javascript
$("#avatar-form").on("submit", function (event) {
  event.preventDefault();
  const formData = new FormData(this);   // includes <input type="file"> fields

  $.ajax({
    url: "/profile/avatar",
    method: "POST",
    data: formData,
    processData: false,   // do not turn FormData into a string
    contentType: false    // let the browser set multipart/form-data with its boundary
  }).done(() => console.log("uploaded"));
});

Both options matter. Without processData: false, jQuery tries to convert the object; without contentType: false, it sends the wrong header and the server cannot read the file.

Protect your write requests

Requests that change data should be protected against CSRF (cross-site request forgery). Frameworks such as Laravel give each page a token; send it with every POST, PUT, PATCH and DELETE, usually as a header set once with $.ajaxSetup() (previous lesson). And validate every value again on the server, exactly as you would for a normal form.

Common mistakes

  • Passing an object as data when the API expects JSON, which sends form encoding.
  • Using dataType: "json" to send JSON. It describes the response.
  • Serialising a form whose fields have no name: they are skipped silently.
  • Forgetting processData: false and contentType: false for file uploads.
  • Sending write requests without CSRF protection.

Exercise

Build a small form with title and body fields. On submit, send it as JSON to https://jsonplaceholder.typicode.com/posts and log the id and title that come back.

Show one possible answer
html
<form id="f"><input name="title" value="Hello"><input name="body" value="World"><button>Send</button></form>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#f").on("submit", function (event) {
    event.preventDefault();
    const data = {};
    $.each($(this).serializeArray(), (i, field) => { data[field.name] = field.value; });

    $.ajax({
      url: "https://jsonplaceholder.typicode.com/posts",
      method: "POST",
      contentType: "application/json",
      data: JSON.stringify(data),
      dataType: "json"
    }).done(saved => console.log(saved.id, saved.title));
  });
</script>
result
101 Hello

Key points

  • $.post(url, data) sends data form-encoded, the same format as a normal HTML form.
  • $(form).serialize() turns every named field into that format, ready to post.
  • To send JSON, set contentType: "application/json" and pass JSON.stringify(data).
  • Files need FormData with processData: false and contentType: false.

Check yourself

1. What format does $.post(url, { name: "Asha" }) send?
2. How do you send a JSON body with $.ajax()?
3. Which fields does .serialize() include?
4. What do you need to upload a file with $.ajax()?