DEV Community

Akhileswar Sathivada
Akhileswar Sathivada

Posted on

Serialization and Deserialization: How Data Travels Between Frontend and Backend

Imagine you're building a web application using React for the frontend and Go for the backend.

A user fills out a form, clicks Submit, and expects the backend to save the information.

The frontend has the data. The backend needs the data. So why can't we simply send the JavaScript object directly to the Go server?

Because the frontend and backend don't necessarily represent data in the same way.

They use different programming languages, different data structures, and different runtime environments. They need a common format to exchange information.

This is where serialization and deserialization come in.

1. The Communication Problem

Let's say a user enters the following details:

const user = {
  name: "Alex",
  age: 24,
  isDeveloper: true
};
Enter fullscreen mode Exit fullscreen mode

Inside JavaScript, this is an object.

But the backend might be written in Go, Python, Java, or another language. Each language has its own way of representing objects and structures.

A JavaScript object isn't automatically a Go struct. The backend cannot simply receive the in-memory JavaScript object and use it.

We need to convert the data into a format that both systems understand.

For most web APIs, that format is JSON.

2. What Is Serialization?

Serialization is the process of converting data structures or objects into a format that can be stored or transmitted.

In our example, we convert the JavaScript object into a JSON string.

const user = {
  name: "Alex",
  age: 24,
  isDeveloper: true
};

const serializedUser = JSON.stringify(user);

console.log(serializedUser);
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "name": "Alex",
  "age": 24,
  "isDeveloper": true
}
Enter fullscreen mode Exit fullscreen mode

The JavaScript object has now been converted into a JSON representation.

This representation can be sent over HTTP, stored in a file, or passed to another system.

Notice the difference:

  • Before serialization: We have a JavaScript object in memory.

  • After serialization: We have a JSON string representing that object.

Serialization doesn't send the original object itself. It creates a representation of the data.

3. What Is Deserialization?

Now let's look at the backend side.

The backend receives the JSON data. But it needs to convert that representation into something it can work with in its own programming language.

Deserialization is the process of converting serialized data back into a usable data structure or object.

For example, imagine our backend is written in Go.

We can define a struct to represent the incoming data:

type User struct {
    Name        string `json:"name"`
    Age         int    `json:"age"`
    IsDeveloper bool   `json:"isDeveloper"`
}
Enter fullscreen mode Exit fullscreen mode

The backend can decode the incoming JSON into this struct:

var user User

err := json.NewDecoder(r.Body).Decode(&user)

if err != nil {
    http.Error(w, "Invalid request body", http.StatusBadRequest)
    return
}

fmt.Println(user.Name)
Enter fullscreen mode Exit fullscreen mode

The JSON data has now been converted into a Go struct.

The backend can access the values using Go's normal syntax.

One important detail: deserialization can fail. For example, the incoming JSON might be malformed or contain values that cannot be decoded into the expected Go types.

That's why backend applications should handle decoding errors rather than assuming every request contains valid data.

4. Following the Complete Request-Response Cycle

Let's connect both concepts.

Suppose a React application sends user information to a Go backend.

The process looks like this:

Frontend

const user = {
  name: "Alex",
  age: 24,
  isDeveloper: true
};

const response = await fetch("/api/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(user)
});
Enter fullscreen mode Exit fullscreen mode

Here's what happens:

  • React has a JavaScript object.

  • JSON.stringify() serializes the object into JSON text.

  • The browser sends the JSON as the HTTP request body.

  • The Go backend receives the request.

  • json.NewDecoder() deserializes the JSON into a Go struct.

  • The backend processes the data.

The reverse happens when the backend sends a response.

Backend

response := User{
    Name:        "Alex",
    Age:         24,
    IsDeveloper: true,
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
Enter fullscreen mode Exit fullscreen mode

The Go struct is serialized into JSON and written to the HTTP response.

Frontend

const data = await response.json();

console.log(data.name);
Enter fullscreen mode Exit fullscreen mode

The browser reads the JSON response and converts it into a JavaScript value.

Complete Flow

       REACT FRONTEND
              |
       JavaScript Object
              |
       JSON.stringify()
              |
        Serialized JSON
              |
          HTTP Request
              |
              v
         GO BACKEND
              |
       JSON Decoder
              |
          Go Struct
              |
       Backend Processing
              |
          Go Struct
              |
       JSON Encoder
              |
        Serialized JSON
              |
         HTTP Response
              |
              v
       REACT FRONTEND
              |
        response.json()
              |
       JavaScript Object
Enter fullscreen mode Exit fullscreen mode

The important thing to understand is that serialization and deserialization happen in both directions.

The frontend serializes data when sending a request and deserializes data when receiving a response. The backend does the opposite.

5. Why JSON?

JSON stands for JavaScript Object Notation.

Despite its name, JSON isn't limited to JavaScript. It is a language-independent data-interchange format supported by many programming languages.

For example:

  • JavaScript uses JSON.stringify() and JSON.parse().

  • Go provides the encoding/json package.

  • Python provides the built-in json module.

  • Java has libraries such as Jackson for JSON processing.

JSON supports a small set of data types:

  • Strings

  • Numbers

  • Booleans

  • Arrays

  • Objects

  • Null

This makes it convenient for exchanging structured data between applications.

However, JSON doesn't preserve every detail of an application's original data structure.

For example, JavaScript has types such as Date, Map, and Set. JSON doesn't have direct equivalents for all of them. A date is commonly represented as a string, and special types need an agreed representation and conversion logic.

So serialization isn't always a perfect copy of an object. It is a conversion into a format that both sides agree to understand.

6. What Happens When the Data Doesn't Match?

Let's say the frontend sends:

{
  "name": "Alex",
  "age": "twenty-four",
  "isDeveloper": true
}
Enter fullscreen mode Exit fullscreen mode

But the Go backend expects:

type User struct {
    Name        string `json:"name"`
    Age         int    `json:"age"`
    IsDeveloper bool   `json:"isDeveloper"`
}
Enter fullscreen mode Exit fullscreen mode

The age field is a string in the incoming JSON, but the backend expects an integer.

Go's JSON decoder cannot decode that string into an int automatically. It returns an error.

This is one reason backend developers validate incoming data.

There are two separate concerns here:

Deserialization: Can the incoming representation be converted into the expected data structure?

Validation: Does the resulting data satisfy the application's requirements?

For example, even if age is successfully decoded as an integer, the application may still reject a negative age.

Successful deserialization doesn't automatically mean the data is valid or safe to use.

7. Is JSON the Only Serialization Format?

No. JSON is popular, particularly for web APIs, but there are other formats.

Format Common Use
JSON REST APIs and general web communication
XML Legacy systems and document-oriented data exchange
Protocol Buffers Efficient structured communication, often in gRPC systems
MessagePack Compact binary serialization
Avro Data serialization in distributed data pipelines

Different formats make different trade-offs.

For example, JSON is human-readable and easy to debug. Protocol Buffers use a compact binary representation and a schema, which can be useful when efficiency and strongly defined message structures matter.

The right format depends on the system, its requirements, and the technologies communicating with each other.

8. A Small Experiment to Understand the Difference

You don't need a complete frontend and backend application to understand the basic concept.

Try this in JavaScript:

const original = {
  name: "Alex",
  age: 24,
  skills: ["JavaScript", "Go"]
};

// Serialization
const serialized = JSON.stringify(original);

console.log("Serialized:", serialized);
console.log("Type:", typeof serialized);

// Deserialization
const deserialized = JSON.parse(serialized);

console.log("Deserialized:", deserialized);
console.log("Type:", typeof deserialized);
Enter fullscreen mode Exit fullscreen mode

Observe the output.

The serialized value is a string. After parsing, you get a JavaScript object again.

Now try:

JSON.parse('{"name": "Alex", "age": }');
Enter fullscreen mode Exit fullscreen mode

This will throw a parsing error because the JSON is malformed.

That small example demonstrates an important point: serialization and deserialization are conversions, and those conversions can fail.

9. What Should a Backend Developer Remember?

Serialization and deserialization are fundamental to communication between different parts of a software system.

Whenever an application exchanges structured data, it needs an agreed representation.

A few things worth remembering:

  • Serialization converts an in-memory data structure into a transferable or storable representation.

  • Deserialization converts that representation back into a usable data structure.

  • JSON is a common format, but it isn't the only option.

  • Both frontend and backend participate in this process.

  • Successful deserialization doesn't guarantee that the data is valid.

  • Backend applications should handle malformed input, type mismatches, and validation failures.

Final Thought

At first, serialization and deserialization might look like simple conversion operations.

But they're part of a much bigger idea: how independent systems communicate without needing to share the same programming language or internal data structures.

Your React frontend doesn't need to understand Go structs, and your Go backend doesn't need to understand JavaScript objects.

They only need to agree on how their data should be represented and exchanged.

That's one of the foundations of backend communication.

Next in the series: Authentication vs Authorization - how does a backend know who is making a request, and what are they allowed to do?

Top comments (0)