or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdeditor-core.mdindex.mdmode-management.mdpreview-mode.mdschema-validation.mdtext-operations.mdtransform-operations.mdtree-operations.md
tile.json

transform-operations.mddocs/

0

# Transform Operations

1

2

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

3

4

## Capabilities

5

6

### Query Configuration

7

8

Configure custom query creation and execution functions for data transformation.

9

10

```javascript { .api }

11

/**

12

* Custom query configuration in editor options

13

*/

14

interface QueryConfiguration {

15

/** Function to create query string from query options */

16

createQuery?: (json: any, queryOptions: QueryOptions) => string;

17

18

/** Function to execute query string on JSON data */

19

executeQuery?: (json: any, query: string) => any;

20

21

/** Description text for the query language */

22

queryDescription?: string;

23

}

24

```

25

26

### Query Options Structure

27

28

Structure for transformation query options used in the Transform modal.

29

30

```javascript { .api }

31

interface QueryOptions {

32

/** Filter configuration */

33

filter?: {

34

/** Field to filter on, or '@' for the value itself */

35

field: string | "@";

36

37

/** Comparison operator */

38

relation: "==" | "!=" | "<" | "<=" | ">" | ">=";

39

40

/** Value to compare against */

41

value: string;

42

};

43

44

/** Sort configuration */

45

sort?: {

46

/** Field to sort by, or '@' for the value itself */

47

field: string | "@";

48

49

/** Sort direction */

50

direction: "asc" | "desc";

51

};

52

53

/** Projection configuration */

54

projection?: {

55

/** Array of field names to include in output */

56

fields: string[];

57

};

58

}

59

```

60

61

**Usage Example:**

62

63

```javascript

64

// Example query options for filtering and sorting users

65

const queryOptions = {

66

filter: {

67

field: "age",

68

relation: ">=",

69

value: "18"

70

},

71

sort: {

72

field: "name",

73

direction: "asc"

74

},

75

projection: {

76

fields: ["name", "email", "age"]

77

}

78

};

79

```

80

81

### Built-in JMESPath Support

82

83

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

84

85

```javascript { .api }

86

// Default JMESPath query functions (internal)

87

const defaultJMESPathConfig = {

88

createQuery: (json, queryOptions) => {

89

// Converts QueryOptions to JMESPath query string

90

// Example output: "users[?age >= `18`] | sort_by(@, &name) | [].{name: name, email: email}"

91

},

92

93

executeQuery: (json, jmespathQuery) => {

94

// Executes JMESPath query on JSON data

95

// Returns transformed data

96

},

97

98

queryDescription: "Uses JMESPath query language. See <a href='http://jmespath.org/'>jmespath.org</a> for syntax."

99

};

100

```

101

102

### Custom Query Language

103

104

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

105

106

```javascript { .api }

107

// Custom SQL-like query language example

108

const customQueryConfig = {

109

createQuery: (json, queryOptions) => {

110

let query = "SELECT";

111

112

// Projection

113

if (queryOptions.projection) {

114

query += " " + queryOptions.projection.fields.join(", ");

115

} else {

116

query += " *";

117

}

118

119

query += " FROM data";

120

121

// Filter

122

if (queryOptions.filter) {

123

const field = queryOptions.filter.field === "@" ? "value" : queryOptions.filter.field;

124

query += ` WHERE ${field} ${queryOptions.filter.relation} '${queryOptions.filter.value}'`;

125

}

126

127

// Sort

128

if (queryOptions.sort) {

129

const field = queryOptions.sort.field === "@" ? "value" : queryOptions.sort.field;

130

query += ` ORDER BY ${field} ${queryOptions.sort.direction.toUpperCase()}`;

131

}

132

133

return query;

134

},

135

136

executeQuery: (json, sqlQuery) => {

137

// Custom SQL-like query execution logic

138

return executeCustomSQL(json, sqlQuery);

139

},

140

141

queryDescription: "Uses a custom SQL-like syntax for data transformation."

142

};

143

144

const options = {

145

mode: "tree",

146

createQuery: customQueryConfig.createQuery,

147

executeQuery: customQueryConfig.executeQuery,

148

queryDescription: customQueryConfig.queryDescription

149

};

150

```

151

152

### Enable/Disable Transform Features

153

154

Control availability of transformation functionality in the editor.

155

156

```javascript { .api }

157

/**

158

* Transform configuration options

159

*/

160

interface TransformOptions {

161

/** Enable transform/filter functionality */

162

enableTransform?: boolean;

163

164

/** Enable sorting functionality */

165

enableSort?: boolean;

166

}

167

```

168

169

**Usage Example:**

170

171

```javascript

172

const options = {

173

mode: "tree",

174

enableTransform: true, // Show Transform button in menu

175

enableSort: true, // Show Sort button in menu

176

177

// Custom transform configuration

178

createQuery: customCreateQuery,

179

executeQuery: customExecuteQuery,

180

queryDescription: "Custom query language for data transformation"

181

};

182

183

const editor = new JSONEditor(container, options);

184

```

185

186

## Built-in Transformation Features

187

188

### Transform Modal

189

190

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

191

192

1. **Filter Step**: Set filtering conditions

193

2. **Sort Step**: Configure sorting options

194

3. **Projection Step**: Select fields to include

195

4. **Preview Step**: Preview results before applying

196

197

### Sort Modal

198

199

The Sort modal allows sorting of arrays and object properties:

200

201

- **Array Sorting**: Sort array elements by value or by object property

202

- **Object Sorting**: Sort object properties by key name or value

203

- **Sort Direction**: Ascending or descending order

204

- **Natural Sort**: Intelligent sorting of strings with numbers

205

206

### JMESPath Query Examples

207

208

Common JMESPath patterns supported by the default query system:

209

210

```javascript

211

// Filter examples

212

"users[?age > `25`]" // Users older than 25

213

"products[?price < `100`]" // Products under $100

214

"items[?contains(name, 'test')]" // Items with 'test' in name

215

216

// Sort examples

217

"sort_by(users, &name)" // Sort users by name (ascending)

218

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

219

220

// Projection examples

221

"users[].{name: name, email: email}" // Select only name and email fields

222

"products[].[name, price]" // Select name and price as arrays

223

224

// Complex transformations

225

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

226

```

227

228

## Advanced Transform Operations

229

230

### Programmatic Data Transformation

231

232

Transform data programmatically without using the UI modals.

233

234

```javascript

235

function transformData(editor, transformFunction) {

236

const currentData = editor.get();

237

const transformedData = transformFunction(currentData);

238

editor.set(transformedData);

239

}

240

241

// Usage examples

242

transformData(editor, (data) => {

243

// Filter array elements

244

if (Array.isArray(data)) {

245

return data.filter(item => item.active === true);

246

}

247

return data;

248

});

249

250

transformData(editor, (data) => {

251

// Sort object properties

252

if (typeof data === 'object' && data !== null) {

253

const sorted = {};

254

Object.keys(data).sort().forEach(key => {

255

sorted[key] = data[key];

256

});

257

return sorted;

258

}

259

return data;

260

});

261

```

262

263

### Batch Transformations

264

265

Apply multiple transformations in sequence.

266

267

```javascript

268

function applyTransformations(editor, transformations) {

269

let data = editor.get();

270

271

transformations.forEach(transform => {

272

data = transform(data);

273

});

274

275

editor.set(data);

276

}

277

278

// Usage

279

const transformations = [

280

// Filter active users

281

(data) => data.users ? { ...data, users: data.users.filter(u => u.active) } : data,

282

283

// Sort users by name

284

(data) => data.users ? { ...data, users: data.users.sort((a, b) => a.name.localeCompare(b.name)) } : data,

285

286

// Add computed field

287

(data) => data.users ? {

288

...data,

289

users: data.users.map(u => ({ ...u, displayName: u.firstName + ' ' + u.lastName }))

290

} : data

291

];

292

293

applyTransformations(editor, transformations);

294

```

295

296

### Custom Transform UI

297

298

Create custom transformation interfaces that integrate with JSONEditor.

299

300

```javascript

301

function createCustomTransformUI(editor) {

302

const transformButton = document.createElement('button');

303

transformButton.textContent = 'Custom Transform';

304

transformButton.onclick = () => {

305

const data = editor.get();

306

307

// Show custom transform dialog

308

showCustomTransformDialog(data, (transformedData) => {

309

editor.set(transformedData);

310

});

311

};

312

313

// Add button to custom toolbar

314

document.getElementById('custom-toolbar').appendChild(transformButton);

315

}

316

317

function showCustomTransformDialog(data, onApply) {

318

// Create modal with custom transformation options

319

const modal = document.createElement('div');

320

modal.className = 'transform-modal';

321

322

// Add transformation controls

323

const controls = createTransformControls(data);

324

modal.appendChild(controls);

325

326

// Apply button

327

const applyButton = document.createElement('button');

328

applyButton.textContent = 'Apply Transform';

329

applyButton.onclick = () => {

330

const transformedData = applyCustomTransform(data, getTransformSettings());

331

onApply(transformedData);

332

document.body.removeChild(modal);

333

};

334

335

modal.appendChild(applyButton);

336

document.body.appendChild(modal);

337

}

338

```

339

340

### Query Result Analysis

341

342

Analyze and validate transformation results.

343

344

```javascript

345

function analyzeTransformResult(originalData, transformedData) {

346

const analysis = {

347

originalSize: JSON.stringify(originalData).length,

348

transformedSize: JSON.stringify(transformedData).length,

349

compressionRatio: 0,

350

itemsChanged: 0,

351

itemsRemoved: 0,

352

itemsAdded: 0

353

};

354

355

analysis.compressionRatio = analysis.transformedSize / analysis.originalSize;

356

357

// Count changes (simplified)

358

if (Array.isArray(originalData) && Array.isArray(transformedData)) {

359

analysis.itemsRemoved = Math.max(0, originalData.length - transformedData.length);

360

analysis.itemsAdded = Math.max(0, transformedData.length - originalData.length);

361

}

362

363

return analysis;

364

}

365

366

// Usage

367

const original = editor.get();

368

const transformed = executeTransform(original, query);

369

const analysis = analyzeTransformResult(original, transformed);

370

371

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

372

```

373

374

## Transform Configuration Examples

375

376

### JMESPath with Custom Description

377

378

```javascript

379

const options = {

380

mode: "tree",

381

enableTransform: true,

382

queryDescription: `

383

<h4>Custom JMESPath Guide</h4>

384

<p>Use JMESPath syntax to filter and transform your data:</p>

385

<ul>

386

<li><code>items[?price < 100]</code> - Filter by price</li>

387

<li><code>sort_by(users, &name)</code> - Sort by name</li>

388

<li><code>users[].{name: name, email: email}</code> - Project fields</li>

389

</ul>

390

<p><a href="https://jmespath.org" target="_blank">Full JMESPath documentation</a></p>

391

`

392

};

393

```

394

395

### GraphQL-style Query Language

396

397

```javascript

398

const graphQLQueryConfig = {

399

createQuery: (json, queryOptions) => {

400

let query = "{\n";

401

402

if (queryOptions.projection) {

403

queryOptions.projection.fields.forEach(field => {

404

query += ` ${field}\n`;

405

});

406

}

407

408

query += "}";

409

410

if (queryOptions.filter) {

411

query += `\nwhere: { ${queryOptions.filter.field}: { ${queryOptions.filter.relation}: "${queryOptions.filter.value}" } }`;

412

}

413

414

return query;

415

},

416

417

executeQuery: (json, graphQLQuery) => {

418

// Custom GraphQL-style execution

419

return executeGraphQLStyleQuery(json, graphQLQuery);

420

},

421

422

queryDescription: "GraphQL-style query syntax for data selection and filtering."

423

};

424

```

425

426

### MongoDB-style Query Language

427

428

```javascript

429

const mongoQueryConfig = {

430

createQuery: (json, queryOptions) => {

431

const pipeline = [];

432

433

// Match stage (filter)

434

if (queryOptions.filter) {

435

const matchStage = { $match: {} };

436

const field = queryOptions.filter.field === "@" ? "_value" : queryOptions.filter.field;

437

438

switch (queryOptions.filter.relation) {

439

case "==":

440

matchStage.$match[field] = queryOptions.filter.value;

441

break;

442

case ">=":

443

matchStage.$match[field] = { $gte: parseFloat(queryOptions.filter.value) };

444

break;

445

// ... other operators

446

}

447

448

pipeline.push(matchStage);

449

}

450

451

// Sort stage

452

if (queryOptions.sort) {

453

const sortStage = { $sort: {} };

454

const field = queryOptions.sort.field === "@" ? "_value" : queryOptions.sort.field;

455

sortStage.$sort[field] = queryOptions.sort.direction === "asc" ? 1 : -1;

456

pipeline.push(sortStage);

457

}

458

459

// Project stage

460

if (queryOptions.projection) {

461

const projectStage = { $project: {} };

462

queryOptions.projection.fields.forEach(field => {

463

projectStage.$project[field] = 1;

464

});

465

pipeline.push(projectStage);

466

}

467

468

return JSON.stringify(pipeline, null, 2);

469

},

470

471

executeQuery: (json, mongoQuery) => {

472

// Execute MongoDB-style aggregation pipeline

473

return executeMongoStyleQuery(json, JSON.parse(mongoQuery));

474

},

475

476

queryDescription: "MongoDB aggregation pipeline syntax for data transformation."

477

};

478

```