JSON (JavaScript Object Notation) has become a ubiquitous data format used for communication between web applications and servers. When your web application sends a request to an API and gets a JSON response back, how do you know if the JSON is valid and structured correctly? Validating the JSON data is important to ensure your application can reliably parse and work with the response.
Some common reasons for validating JSON:
- Avoid exceptions and errors when trying to parse malformed JSON
- Confirm the JSON matches the structure you expect from the API contract
- Check for missing required fields in the JSON
- Verify field names and data types are correct
In this article, we’ll explore different techniques for validating JSON responses in JavaScript. We’ll look at the following approaches:
JSON Schema Validation
Use a JSON schema to define the expected structure and validate the JSON against it. JSON schema is a powerful standard that provides validation and documentation for JSON data.
Manual Validation
Manually write validation code to check the JSON structure and values. This gives you flexibility to validate aspects not covered by JSON schema.
Unit Testing
Write unit tests that validate JSON responses coming from API calls. This helps catch issues early during development.
Linting
Use a JSON linter to check for syntax errors and standards compliance. A linter can catch low-level issues like missing commas that may cause parsing to fail.
We’ll provide code examples using each technique and discuss the pros and cons. By the end, you’ll have strategies to validate JSON responses in any JavaScript project. Let’s get started!
JSON Schema Validation
JSON Schema is a vocabulary that allows you to define JSON data structures and the constraints they must follow. Some key aspects it can define:
- Required fields
- Data types (string, number, array, etc)
- Allowed values or patterns
- Object depth/hierarchy
- Field formatting (date, email, etc)
With JSON schema, you define a schema file that models your JSON data structure. The schema acts as a contract or blueprint for the JSON. You then validate that a given JSON object matches the schema, which ensures the object meets the defined requirements.
Let’s walk through an example to see JSON schema validation in practice.
First, we’ll define a simple JSON schema that describes a product:
{ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Product", "type": "object", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "price": { "type": "number", "exclusiveMinimum": 0 } }, "required": ["id", "name", "price"] }
This schema does a few things:
- Specifies the JSON object should have id, name, and price fields
- id must be an integer
- name must be a string
- price must be a number greater than 0
- All three fields are required
Now let’s look at some sample JSON for a product:
{ "id": 123, "name": "Football", "price": 29.99 }
We can validate that this JSON matches our schema using a JSON schema validator. There are validators available both online and as JavaScript packages that can be included in a project.
Here is an example using the tv4 JSON schema validator package for Node.js:
const tv4 = require('tv4'); const productSchema = { // schema definition above }; const product = { // product JSON above }; const valid = tv4.validate(product, productSchema); if (!valid) { console.log("JSON is invalid!"); console.log(tv4.error); } else { console.log("JSON is valid!"); }
The validate method compares the product JSON against the schema and returns true or false. The error details are also available when validation fails.
This is a straightforward example, but JSON schema works for complex validation too. You can define nested objects, arrays, default values, custom validation logic, and more.
**Pros:**
- Reusable validation based on a schema
- Standard validation vocabulary
- Shared schema can provide documentation
- Good for complex validation
**Cons:**
- Requires defining a separate schema
- Only validates structure & constraints, not business logic
JSON schema is ideal when you need to validate across multiple parts of your codebase, or share validation logic between projects. But sometimes a simple manual validation is more concise for a specific use case.
Manual Validation
For simple JSON validation, manually writing validation code may be all you need. Here are some examples of validating a JSON response in JavaScript:
// Response from API const response = { id: 123, name: "Football" }; // Validate response contains expected fields if (!response.id || !response.name) { throw new Error("Response missing required fields!"); } // Validate types if (typeof response.id !== "number") { throw new Error("id must be a number!"); } if (typeof response.name !== "string") { throw new Error("name must be a string!"); }
This validates that the required fields exist, and are the expected types. You can add additional validation like this for other business rules:
// Validate business rules if (response.price < 0) { throw new Error("price cannot be negative!"); } if (response.name.length > 40) { throw new Error("name is too long!"); }
You can also define reusable validation functions to avoid duplicating logic:
function validateProduct(product) { if (!product.id || !product.name) { throw new Error("Missing fields!"); } // Additional validations... return true; } const valid = validateProduct(response);
**Pros:**
- No additional schemas required
- Validate business logic
- Easy to understand
**Cons:**
- Validation logic must be re-written across code
- Only validates one object at a time
- Harder to validate complex structures
Manual validation works well for straightforward cases when you just need to validate an object instance in one place. But for more complex needs, JSON schema or unit tests may be better options.
Unit Testing
Unit tests validate the functionality of your code by exercising it with different inputs and conditions and asserting the results are correct.
They provide a great opportunity to validate that your application handles JSON responses properly. Some examples:
- Call an API method in a test and validate the response JSON
- Mock a response and pass it to a parse method, validating no errors occur
- Check edge cases like missing fields or invalid data types
Here is an example unit test validating a JSON response:
// Response from example API call const response = { id: 'abc', name: 'Product' }; try { // Pass to application code that parses response const product = parseProduct(response); // Assertions if (product.id !== 'abc') { throw Error("ID mismatch"); } if (product.name !== 'Product') { throw Error("Name mismatch"); } } catch (error) { // Test failed assert.fail("parseProduct failed!"); } // If no assertions failed, test passes assert.pass("parseProduct works");
This test calls parseProduct() with an example response, and verifies that the parsed product contains the expected data. If anything fails, an assertion will fail indicating the test does not pass.
We can expand on this with additional tests covering different cases:
// Additional tests // Validate required fields const responseMissingName = { id: 'abc' }; assert.throws(() => { parseProduct(responseMissingName); }); // Validate data types const responseInvalidType = { id: 123, name: true // invalid type }; assert.throws(() => { parseProduct(responseInvalidType); });
This helps ensure the code handles malformed or unexpected data properly.
The great thing about unit testing is it pushes you to write testable, reusable validation code. Ideally the parseProduct() method encapsulates the validation logic so it can be tested in isolation.
**Pros:**
- Tests wide range of JSON responses
- Catches bugs early
- Encourages modular/testable code
- Executed on every code change
**Cons:**
- Requires writing comprehensive tests
- Only supplements run-time validation
Testing checks logic works as expected, but doesn’t replace validating real JSON responses. Use unit testing in combination with other techniques for best results.
JSON Linting
JSON linting checks for syntax errors and adherence to the JSON standard. A linter verifies:
- JSON is valid overall
- Correct commas between fields
- Quotes around keys/string values
- No trailing commas at end
For example:
{ "id" 123, // Missing quotes around id "name": "Product" }
A linter would catch the missing quotes around the id key here.
Linting helps avoid mismatches between what an API returns and what your JSON parser expects that could cause hard-to-debug errors.
Let’s look at an example using the jsonlint package for Node.js:
const jsonlint = require("jsonlint"); const response = `{ "id": 123 // missing comma }`; const isValid = jsonlint.parse(response); // isValid = false // Error returned: // Expected comma before next property at line 2 column 17
The parse() method returns true if valid, or false with an error detailing issues found.
Most linting is done pre-commit or during build processes versus at run-time. But you may want to consider doing an extra JSON lint in production if an API response is business critical.
**Pros:**
- Catches minor syntax issues
- Lightweight to implement
- Prevents parsing failures
**Cons:**
- Only validates format not logic
- Usually runs before deployment
Linting provides a baseline level of checking that gives you confidence before parsing JSON. Use with other validation approaches for comprehensive protection.
Conclusion
To recap, here are some best practices for validating JSON:
- Use JSON schema for complex, reusable validation
- Manually validate where schema would be overkill
- Write unit tests to cover range of expected responses
- Lint JSON before parsing to catch syntax issues
- Validate critical JSON at run-time against schema
- Encapsulate validation logic into reusable modules
Choose the right level of validation for your use case, and combine methods as needed. This ensures your application parses JSON reliably and avoids difficult to diagnose runtime errors.
Validating JSON responses is an important step to building robust applications that integrate smoothly with APIs. Using the right strategy optimizes development and catches problems immediately.
Hopefully this gives you some options to validate JSON responses in your next JavaScript project. Happy coding!