Filter JSON Arrays in JavaScript
Array.filter() is the standard way to select elements from a JSON array that meet a condition. It returns a new array without modifying the original, making it safe for functional patterns and React state updates. This guide covers filtering by value, string search, nested properties, multiple conditions, and TypeScript patterns.
Validate JSON before filtering — paste your array into Jsonic's formatter.
Open JSON FormatterFilter a parsed JSON array
The most common starting point: parse a JSON string with JSON.parse, then call filter() on the resulting array. The callback receives each element and returns true to keep it or false to exclude it.
const json = '[{"name":"Alice","age":30,"active":true},{"name":"Bob","age":25,"active":false},{"name":"Carol","age":35,"active":true}]';
// Parse the JSON string first
const users = JSON.parse(json);
// Filter: keep only active users
const active = users.filter(user => user.active);
console.log(active.length); // 2
// Filter: age >= 30
const senior = users.filter(user => user.age >= 30);
console.log(senior.map(u => u.name)); // ["Alice", "Carol"]filter() always returns a new array. If no elements match the condition, it returns an empty array — never null or undefined.
Filter by exact string value
Use strict equality (===) for exact matches, .includes() for partial string matches, or lowercase conversion for case-insensitive comparisons.
const products = [
{ id: 1, category: "electronics", name: "Phone" },
{ id: 2, category: "clothing", name: "Shirt" },
{ id: 3, category: "electronics", name: "Laptop" },
{ id: 4, category: "books", name: "Novel" },
];
// Exact match
const electronics = products.filter(p => p.category === "electronics");
// [{ id: 1, ... }, { id: 3, ... }]
// Includes/partial match
const withPhone = products.filter(p => p.name.includes("phone"));
// Case-insensitive exact match
const query = "Electronics";
const caseInsensitive = products.filter(
p => p.category.toLowerCase() === query.toLowerCase()
);Filter by number range
Combine comparison operators inside the callback to build range filters. This is the standard pattern for price sliders, age brackets, and quantity thresholds.
const orders = [
{ id: 1, total: 15.50, items: 2 },
{ id: 2, total: 89.99, items: 5 },
{ id: 3, total: 5.00, items: 1 },
{ id: 4, total: 250.00, items: 12 },
];
// Price range filter
const midRange = orders.filter(o => o.total >= 10 && o.total <= 100);
// [{ id: 1, ... }, { id: 2, ... }]
// Single condition
const large = orders.filter(o => o.items > 4);
// [{ id: 2, ... }, { id: 4, ... }]Filter by multiple conditions (AND and OR)
Use && to require all conditions and || to require at least one. For complex logic, extract named predicate functions to keep the callback readable.
const employees = [
{ name: "Alice", dept: "eng", salary: 95000, senior: true },
{ name: "Bob", dept: "hr", salary: 65000, senior: false },
{ name: "Carol", dept: "eng", salary: 110000, senior: true },
{ name: "Dave", dept: "eng", salary: 72000, senior: false },
];
// AND: must meet both conditions
const seniorEngineers = employees.filter(
e => e.dept === "eng" && e.senior === true
);
// [Alice, Carol]
// OR: must meet at least one condition
const highEarnerOrSenior = employees.filter(
e => e.salary > 100000 || e.senior === true
);
// [Alice, Carol]
// Combination
const target = employees.filter(
e => e.dept === "eng" && (e.salary > 90000 || e.senior)
);Filter by nested object property
Access nested properties with dot notation inside the callback. Use optional chaining (?.) to avoid a TypeError when an intermediate property might be undefined.
const orders = [
{ id: 1, customer: { name: "Alice", country: "US" }, total: 50 },
{ id: 2, customer: { name: "Bob", country: "UK" }, total: 30 },
{ id: 3, customer: { name: "Carol", country: "US" }, total: 80 },
];
// Filter by nested property
const usOrders = orders.filter(o => o.customer.country === "US");
// [{ id: 1 }, { id: 3 }]
// Safe access with optional chaining
const withCity = orders.filter(o => o.customer?.city === "London");Without optional chaining, accessing a missing nested property throws TypeError: Cannot read properties of undefined. The ?. operator short-circuits to undefined instead, which is falsy and safely excluded.
Remove nulls and filter falsy values
Pass Boolean directly as the callback to remove all falsy values in one step. Use loose inequality (!= null) when you want to keep 0, false, and empty strings but remove only null and undefined.
const mixed = [1, null, "hello", undefined, 0, false, "", 42, null];
// Remove all falsy values (null, undefined, 0, '', false)
const truthy = mixed.filter(Boolean);
// [1, "hello", 42]
// Remove only null and undefined
const noNulls = mixed.filter(item => item != null);
// [1, "hello", 0, false, "", 42]
// Remove nulls from an array of objects
const users = [
{ id: 1, name: "Alice" },
null,
{ id: 2, name: "Bob" },
undefined,
];
const validUsers = users.filter(Boolean);
// [{ id: 1 }, { id: 2 }]Filter and transform with filter + map
Chain filter() and map() to select elements and reshape them in a single pipeline. Because both methods return new arrays, chaining is safe and non-destructive.
const products = [
{ id: 1, name: "Phone", price: 599, active: true },
{ id: 2, name: "Case", price: 19, active: false },
{ id: 3, name: "Tablet", price: 399, active: true },
];
// Filter active items, then extract just names
const activeNames = products
.filter(p => p.active)
.map(p => p.name);
// ["Phone", "Tablet"]
// Filter by price, then apply a discount
const discounted = products
.filter(p => p.active && p.price > 100)
.map(p => ({ ...p, price: p.price * 0.9 }));Always put filter() before map() in the chain. Filtering first reduces the number of elements that map() has to process.
TypeScript type-safe filter
TypeScript infers the return type of filter() as the same type as the input array. For narrowing to a more specific subtype, use a type guard function with the item is T return type syntax.
interface User {
id: number;
name: string;
role: "admin" | "viewer" | "editor";
active: boolean;
}
const users: User[] = [
{ id: 1, name: "Alice", role: "admin", active: true },
{ id: 2, name: "Bob", role: "viewer", active: false },
{ id: 3, name: "Carol", role: "admin", active: true },
];
// Type is inferred as User[]
const admins = users.filter(u => u.role === "admin");
// Type guard for narrowing
function isAdmin(user: User): user is User & { role: "admin" } {
return user.role === "admin";
}
const typedAdmins = users.filter(isAdmin);Filter pattern quick reference
| Pattern | Code | Use when |
|---|---|---|
| Exact match | item.key === value | Fixed value comparison |
| Includes | item.str.includes(query) | Partial string match |
| Case-insensitive | item.str.toLowerCase() === q.toLowerCase() | Search input |
| Range | item.num >= min && item.num <= max | Numeric range |
| Nested property | item.nested?.prop === value | Optional chaining |
| Remove nulls | Boolean | Clean sparse arrays |
| Multiple AND | cond1 && cond2 | Must meet all |
| Multiple OR | cond1 || cond2 | Meet any one |
Frequently asked questions
What does Array.filter return?
Array.filter returns a new array containing only the elements for which the callback returned a truthy value. The original array is not modified. If no elements pass the test, it returns an empty array — never null or undefined. The returned array maintains the order of the original.
How do I filter a JSON array by a specific property value?
Parse the JSON string first with JSON.parse, then apply filter: const filtered = JSON.parse(json).filter(item => item.status === 'active'). The callback receives each element and should return true to keep it or false to exclude it.
How do I filter out null and undefined values from a JSON array?
Use Boolean as the callback: const clean = array.filter(Boolean). This removes null, undefined, 0, '', and false. To remove only null and undefined specifically, use array.filter(item => item != null) — the loose inequality removes both null and undefined.
How do I filter by multiple conditions in JavaScript?
Combine conditions with && (AND) or || (OR) inside the callback: array.filter(item => item.age >= 18 && item.active === true). For complex conditions, extract named predicates: const isAdult = item => item.age >= 18; array.filter(item => isAdult(item) && item.verified).
How do I do a case-insensitive string filter?
Convert both the property and the search term to the same case before comparing: array.filter(item => item.name.toLowerCase().includes(query.toLowerCase())). For exact-match case-insensitive, use item.name.toLowerCase() === query.toLowerCase(). This is the standard pattern for search boxes.
How do I filter a deeply nested JSON array?
Access nested properties with dot notation in the callback: array.filter(item => item.address?.city === 'London'). Use optional chaining (?.) to avoid errors when a nested property might be missing. For deeply nested arrays, you may need to combine filter with flatMap or reduce.
Inspect your JSON array structure before filtering
Paste your JSON into Jsonic's formatter to validate and pretty-print it.
Open JSON Formatter