code icon Code

Sort JSON Array

Sort array by field value

Source Code

import fs from "fs";
import path from "path";

const [inputPath, field, order = "asc", outputPath] = process.argv.slice(2);

if (!inputPath || !field || !outputPath) {
  console.error("Usage: inputPath field [order] outputPath");
  process.exit(1);
}

/**
 * Get nested field value using dot notation
 */
function getField(obj, fieldPath) {
  const parts = fieldPath.split(".");
  let value = obj;
  for (const part of parts) {
    if (value == null) return undefined;
    value = value[part];
  }
  return value;
}

/**
 * Compare two values for sorting
 */
function compare(a, b) {
  // Handle null/undefined
  if (a == null && b == null) return 0;
  if (a == null) return 1;
  if (b == null) return -1;

  // Try numeric comparison
  const numA = Number(a);
  const numB = Number(b);
  if (!isNaN(numA) && !isNaN(numB)) {
    return numA - numB;
  }

  // Try date comparison
  const dateA = new Date(a);
  const dateB = new Date(b);
  if (!isNaN(dateA.getTime()) && !isNaN(dateB.getTime())) {
    return dateA.getTime() - dateB.getTime();
  }

  // String comparison
  return String(a).localeCompare(String(b));
}

try {
  console.log(`Reading ${inputPath}...`);
  const raw = fs.readFileSync(inputPath, "utf-8");
  const data = JSON.parse(raw);

  const items = Array.isArray(data)
    ? data
    : data.items || data.results || data.messages || [];

  if (!Array.isArray(items)) {
    console.error("Input must be a JSON array or object with array property");
    process.exit(1);
  }

  const isDesc = order.toLowerCase() === "desc";
  console.log(`Sorting ${items.length} items by ${field} (${isDesc ? "descending" : "ascending"})...`);

  const sorted = [...items].sort((a, b) => {
    const valA = getField(a, field);
    const valB = getField(b, field);
    const result = compare(valA, valB);
    return isDesc ? -result : result;
  });

  // Ensure output directory exists
  const dir = path.dirname(outputPath);
  if (dir && dir !== ".") {
    fs.mkdirSync(dir, { recursive: true });
  }

  fs.writeFileSync(outputPath, JSON.stringify(sorted, null, 2));

  console.log(`\nāœ“ Sorted ${items.length} items by ${field} (${isDesc ? "desc" : "asc"})`);
  console.log(`  Written to: ${outputPath}`);

  // Show first and last values
  if (sorted.length > 0) {
    const first = getField(sorted[0], field);
    const last = getField(sorted[sorted.length - 1], field);
    console.log(`  First: ${first}`);
    console.log(`  Last: ${last}`);
  }

  console.log(
    JSON.stringify({
      success: true,
      outputPath,
      count: sorted.length,
      field,
      order: isDesc ? "desc" : "asc",
    })
  );
} catch (error) {
  console.error("Error:", error.message);
  process.exit(1);
}