JSON (JavaScript Object Notation) is a text-based, lightweight format built on JavaScript's object syntax. It is easy for humans to read and write, and easy for machines to parse and generate. According to json.org, JSON rests on two universal structures:

  • a collection of name/value pairs (an object, starting with {, ending with })
  • an ordered list of values (an array, starting with [, ending with ])

A value is a string in double quotes, a number, true, false, null, an object, or an array; these structures can be nested arbitrarily. JSON is language-independent but uses conventions from the C family and is documented in ECMA-404 as a data interchange standard. In web applications, JSON is typically transferred between server and client and converted between text and object using JSON.parse() and JSON.stringify().

XML is the older, considerably more verbose markup format. It's used by, among others, SOAP, and describes its structure via schemas such as XSD. The tag-based notation creates more overhead than JSON, but in exchange XML offers powerful tools for validation, namespaces, and document structures, which keeps it relevant in enterprise and government contexts.

According to protobuf.dev, Protocol Buffers are a language- and platform-neutral, extensible mechanism for serializing structured data, similar to JSON, but smaller and faster, with generated native language bindings. You define the data structure once in a .proto file; the proto compiler generates code from it for reading and writing. Key properties:

  • binary and compact, suited for packets of typed data up to a few megabytes
  • schema-driven with typed fields instead of free-form text structure
  • extensible, without invalidating existing data or forcing code changes
  • suited both for transient network traffic and for long-term storage

Protocol Buffers are the most widely used data format at Google and form the basis for gRPC. Downside: the binary form isn't directly human-readable and requires the schema to interpret it.

YAML also plays a role, mainly for configuration and specifications (such as OpenAPI), less so for runtime data exchange.

Content-Type and content negotiation: according to MDN, content negotiation is the HTTP mechanism for serving different representations of a resource under the same URI. In server-driven (proactive) negotiation, the client sends headers such as Accept, and the server picks the matching variant. If none fits, it responds with status codes such as 406 Not Acceptable or 415 Unsupported Media Type. This is how an API signals, via the media type (such as application/json or application/xml), the format in which the request and response are encoded.

When to use what: JSON is the pragmatic standard for web and REST APIs (readable, broadly supported). XML pays off with SOAP, strict schema validation, or existing enterprise standards. Protocol Buffers fit high throughput, low latency, and service-to-service communication over gRPC, where compactness and type safety matter more than direct readability.

Protocol Buffers, JSON, and HTTP negotiation
// .proto schema (Protocol Buffers)
syntax = "proto3";
message User {
  int32 id = 1;
  string name = 2;
  bool active = 3;
}

// the same data as JSON
{
  "id": 1,
  "name": "Anna",
  "active": true
}

// HTTP negotiation of the format
GET /api/user/1
Accept: application/json
-> 200 OK
   Content-Type: application/json

The same data object as a typed Protobuf schema and as JSON; the Accept and Content-Type headers control which representation HTTP delivers.

Sources

Keep reading