CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jsoneditor

A web-based tool to view, edit, format, and validate JSON with multiple editing modes including tree, code, text, and preview

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

transform-operations.mddocs/

Transform Operations

JMESPath-based data transformation and filtering capabilities with custom query language support, sorting functionality, and data manipulation tools.

Capabilities

Query Configuration

Configure custom query creation and execution functions for data transformation.

/**
 * Custom query configuration in editor options
 */
interface QueryConfiguration {
  /** Function to create query string from query options */
  createQuery?: (json: any, queryOptions: QueryOptions) => string;
  
  /** Function to execute query string on JSON data */
  executeQuery?: (json: any, query: string) => any;
  
  /** Description text for the query language */
  queryDescription?: string;
}

Query Options Structure

Structure for transformation query options used in the Transform modal.

interface QueryOptions {
  /** Filter configuration */
  filter?: {
    /** Field to filter on, or '@' for the value itself */
    field: string | "@";
    
    /** Comparison operator */
    relation: "==" | "!=" | "<" | "<=" | ">" | ">=";
    
    /** Value to compare against */
    value: string;
  };
  
  /** Sort configuration */
  sort?: {
    /** Field to sort by, or '@' for the value itself */
    field: string | "@";
    
    /** Sort direction */
    direction: "asc" | "desc";
  };
  
  /** Projection configuration */
  projection?: {
    /** Array of field names to include in output */
    fields: string[];
  };
}

Usage Example:

// Example query options for filtering and sorting users
const queryOptions = {
  filter: {
    field: "age",
    relation: ">=",
    value: "18"
  },
  sort: {
    field: "name", 
    direction: "asc"
  },
  projection: {
    fields: ["name", "email", "age"]
  }
};

Built-in JMESPath Support

JSONEditor includes built-in JMESPath query support for data transformation.

// Default JMESPath query functions (internal)
const defaultJMESPathConfig = {
  createQuery: (json, queryOptions) => {
    // Converts QueryOptions to JMESPath query string
    // Example output: "users[?age >= `18`] | sort_by(@, &name) | [].{name: name, email: email}"
  },
  
  executeQuery: (json, jmespathQuery) => {
    // Executes JMESPath query on JSON data
    // Returns transformed data
  },
  
  queryDescription: "Uses JMESPath query language. See <a href='http://jmespath.org/'>jmespath.org</a> for syntax."
};

Custom Query Language

Implement a custom query language to replace the default JMESPath functionality.

// Custom SQL-like query language example
const customQueryConfig = {
  createQuery: (json, queryOptions) => {
    let query = "SELECT";
    
    // Projection
    if (queryOptions.projection) {
      query += " " + queryOptions.projection.fields.join(", ");
    } else {
      query += " *";
    }
    
    query += " FROM data";
    
    // Filter
    if (queryOptions.filter) {
      const field = queryOptions.filter.field === "@" ? "value" : queryOptions.filter.field;
      query += ` WHERE ${field} ${queryOptions.filter.relation} '${queryOptions.filter.value}'`;
    }
    
    // Sort
    if (queryOptions.sort) {
      const field = queryOptions.sort.field === "@" ? "value" : queryOptions.sort.field;
      query += ` ORDER BY ${field} ${queryOptions.sort.direction.toUpperCase()}`;
    }
    
    return query;
  },
  
  executeQuery: (json, sqlQuery) => {
    // Custom SQL-like query execution logic
    return executeCustomSQL(json, sqlQuery);
  },
  
  queryDescription: "Uses a custom SQL-like syntax for data transformation."
};

const options = {
  mode: "tree",
  createQuery: customQueryConfig.createQuery,
  executeQuery: customQueryConfig.executeQuery,
  queryDescription: customQueryConfig.queryDescription
};

Enable/Disable Transform Features

Control availability of transformation functionality in the editor.

/**
 * Transform configuration options
 */
interface TransformOptions {
  /** Enable transform/filter functionality */
  enableTransform?: boolean;
  
  /** Enable sorting functionality */
  enableSort?: boolean;
}

Usage Example:

const options = {
  mode: "tree",
  enableTransform: true,  // Show Transform button in menu
  enableSort: true,       // Show Sort button in menu
  
  // Custom transform configuration
  createQuery: customCreateQuery,
  executeQuery: customExecuteQuery,
  queryDescription: "Custom query language for data transformation"
};

const editor = new JSONEditor(container, options);

Built-in Transformation Features

Transform Modal

The Transform modal provides a wizard-like interface for building queries:

  1. Filter Step: Set filtering conditions
  2. Sort Step: Configure sorting options
  3. Projection Step: Select fields to include
  4. Preview Step: Preview results before applying

Sort Modal

The Sort modal allows sorting of arrays and object properties:

  • Array Sorting: Sort array elements by value or by object property
  • Object Sorting: Sort object properties by key name or value
  • Sort Direction: Ascending or descending order
  • Natural Sort: Intelligent sorting of strings with numbers

JMESPath Query Examples

Common JMESPath patterns supported by the default query system:

// Filter examples
"users[?age > `25`]"                    // Users older than 25
"products[?price < `100`]"              // Products under $100
"items[?contains(name, 'test')]"        // Items with 'test' in name

// Sort examples  
"sort_by(users, &name)"                 // Sort users by name (ascending)
"reverse(sort_by(users, &age))"         // Sort users by age (descending)

// Projection examples
"users[].{name: name, email: email}"    // Select only name and email fields
"products[].[name, price]"              // Select name and price as arrays

// Complex transformations
"users[?age >= `18`] | sort_by(@, &name) | [].{name: name, adult: `true`}"

Advanced Transform Operations

Programmatic Data Transformation

Transform data programmatically without using the UI modals.

function transformData(editor, transformFunction) {
  const currentData = editor.get();
  const transformedData = transformFunction(currentData);
  editor.set(transformedData);
}

// Usage examples
transformData(editor, (data) => {
  // Filter array elements
  if (Array.isArray(data)) {
    return data.filter(item => item.active === true);
  }
  return data;
});

transformData(editor, (data) => {
  // Sort object properties
  if (typeof data === 'object' && data !== null) {
    const sorted = {};
    Object.keys(data).sort().forEach(key => {
      sorted[key] = data[key];
    });
    return sorted;
  }
  return data;
});

Batch Transformations

Apply multiple transformations in sequence.

function applyTransformations(editor, transformations) {
  let data = editor.get();
  
  transformations.forEach(transform => {
    data = transform(data);
  });
  
  editor.set(data);
}

// Usage
const transformations = [
  // Filter active users
  (data) => data.users ? { ...data, users: data.users.filter(u => u.active) } : data,
  
  // Sort users by name
  (data) => data.users ? { ...data, users: data.users.sort((a, b) => a.name.localeCompare(b.name)) } : data,
  
  // Add computed field
  (data) => data.users ? { 
    ...data, 
    users: data.users.map(u => ({ ...u, displayName: u.firstName + ' ' + u.lastName }))
  } : data
];

applyTransformations(editor, transformations);

Custom Transform UI

Create custom transformation interfaces that integrate with JSONEditor.

function createCustomTransformUI(editor) {
  const transformButton = document.createElement('button');
  transformButton.textContent = 'Custom Transform';
  transformButton.onclick = () => {
    const data = editor.get();
    
    // Show custom transform dialog
    showCustomTransformDialog(data, (transformedData) => {
      editor.set(transformedData);
    });
  };
  
  // Add button to custom toolbar
  document.getElementById('custom-toolbar').appendChild(transformButton);
}

function showCustomTransformDialog(data, onApply) {
  // Create modal with custom transformation options
  const modal = document.createElement('div');
  modal.className = 'transform-modal';
  
  // Add transformation controls
  const controls = createTransformControls(data);
  modal.appendChild(controls);
  
  // Apply button
  const applyButton = document.createElement('button');
  applyButton.textContent = 'Apply Transform';
  applyButton.onclick = () => {
    const transformedData = applyCustomTransform(data, getTransformSettings());
    onApply(transformedData);
    document.body.removeChild(modal);
  };
  
  modal.appendChild(applyButton);
  document.body.appendChild(modal);
}

Query Result Analysis

Analyze and validate transformation results.

function analyzeTransformResult(originalData, transformedData) {
  const analysis = {
    originalSize: JSON.stringify(originalData).length,
    transformedSize: JSON.stringify(transformedData).length,
    compressionRatio: 0,
    itemsChanged: 0,
    itemsRemoved: 0,
    itemsAdded: 0
  };
  
  analysis.compressionRatio = analysis.transformedSize / analysis.originalSize;
  
  // Count changes (simplified)
  if (Array.isArray(originalData) && Array.isArray(transformedData)) {
    analysis.itemsRemoved = Math.max(0, originalData.length - transformedData.length);
    analysis.itemsAdded = Math.max(0, transformedData.length - originalData.length);
  }
  
  return analysis;
}

// Usage
const original = editor.get();
const transformed = executeTransform(original, query);
const analysis = analyzeTransformResult(original, transformed);

console.log(`Transform reduced size by ${((1 - analysis.compressionRatio) * 100).toFixed(1)}%`);

Transform Configuration Examples

JMESPath with Custom Description

const options = {
  mode: "tree",
  enableTransform: true,
  queryDescription: `
    <h4>Custom JMESPath Guide</h4>
    <p>Use JMESPath syntax to filter and transform your data:</p>
    <ul>
      <li><code>items[?price < 100]</code> - Filter by price</li>
      <li><code>sort_by(users, &name)</code> - Sort by name</li>
      <li><code>users[].{name: name, email: email}</code> - Project fields</li>
    </ul>
    <p><a href="https://jmespath.org" target="_blank">Full JMESPath documentation</a></p>
  `
};

GraphQL-style Query Language

const graphQLQueryConfig = {
  createQuery: (json, queryOptions) => {
    let query = "{\n";
    
    if (queryOptions.projection) {
      queryOptions.projection.fields.forEach(field => {
        query += `  ${field}\n`;
      });
    }
    
    query += "}";
    
    if (queryOptions.filter) {
      query += `\nwhere: { ${queryOptions.filter.field}: { ${queryOptions.filter.relation}: "${queryOptions.filter.value}" } }`;
    }
    
    return query;
  },
  
  executeQuery: (json, graphQLQuery) => {
    // Custom GraphQL-style execution
    return executeGraphQLStyleQuery(json, graphQLQuery);
  },
  
  queryDescription: "GraphQL-style query syntax for data selection and filtering."
};

MongoDB-style Query Language

const mongoQueryConfig = {
  createQuery: (json, queryOptions) => {
    const pipeline = [];
    
    // Match stage (filter)
    if (queryOptions.filter) {
      const matchStage = { $match: {} };
      const field = queryOptions.filter.field === "@" ? "_value" : queryOptions.filter.field;
      
      switch (queryOptions.filter.relation) {
        case "==":
          matchStage.$match[field] = queryOptions.filter.value;
          break;
        case ">=":
          matchStage.$match[field] = { $gte: parseFloat(queryOptions.filter.value) };
          break;
        // ... other operators
      }
      
      pipeline.push(matchStage);
    }
    
    // Sort stage
    if (queryOptions.sort) {
      const sortStage = { $sort: {} };
      const field = queryOptions.sort.field === "@" ? "_value" : queryOptions.sort.field;
      sortStage.$sort[field] = queryOptions.sort.direction === "asc" ? 1 : -1;
      pipeline.push(sortStage);
    }
    
    // Project stage
    if (queryOptions.projection) {
      const projectStage = { $project: {} };
      queryOptions.projection.fields.forEach(field => {
        projectStage.$project[field] = 1;
      });
      pipeline.push(projectStage);
    }
    
    return JSON.stringify(pipeline, null, 2);
  },
  
  executeQuery: (json, mongoQuery) => {
    // Execute MongoDB-style aggregation pipeline
    return executeMongoStyleQuery(json, JSON.parse(mongoQuery));
  },
  
  queryDescription: "MongoDB aggregation pipeline syntax for data transformation."
};

docs

configuration.md

editor-core.md

index.md

mode-management.md

preview-mode.md

schema-validation.md

text-operations.md

transform-operations.md

tree-operations.md

tile.json