Initial commit: JMESPath Testing Tool
- React-based web application for testing JMESPath expressions - macOS-first containerization with Apple container command - Bootstrap UI with real-time evaluation - GitHub Actions CI/CD pipeline - Docker fallback support - Comprehensive documentation and development scripts
This commit is contained in:
240
src/App.js
Normal file
240
src/App.js
Normal file
@@ -0,0 +1,240 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import jmespath from 'jmespath';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
const [jmespathExpression, setJmespathExpression] = useState('people[0].name');
|
||||
const [jsonData, setJsonData] = useState(`{
|
||||
"people": [
|
||||
{
|
||||
"name": "John Doe",
|
||||
"age": 30,
|
||||
"city": "New York"
|
||||
},
|
||||
{
|
||||
"name": "Jane Smith",
|
||||
"age": 25,
|
||||
"city": "Los Angeles"
|
||||
}
|
||||
],
|
||||
"total": 2
|
||||
}`);
|
||||
const [result, setResult] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const [jsonError, setJsonError] = useState('');
|
||||
|
||||
const evaluateExpression = () => {
|
||||
try {
|
||||
// Clear previous errors
|
||||
setError('');
|
||||
setJsonError('');
|
||||
|
||||
// Validate and parse JSON
|
||||
let parsedData;
|
||||
try {
|
||||
parsedData = JSON.parse(jsonData);
|
||||
} catch (jsonErr) {
|
||||
setJsonError(`Invalid JSON: ${jsonErr.message}`);
|
||||
setResult('');
|
||||
return;
|
||||
}
|
||||
|
||||
// Evaluate JMESPath expression
|
||||
const queryResult = jmespath.search(parsedData, jmespathExpression);
|
||||
|
||||
// Format the result
|
||||
if (queryResult === null || queryResult === undefined) {
|
||||
setResult('null');
|
||||
} else {
|
||||
setResult(JSON.stringify(queryResult, null, 2));
|
||||
}
|
||||
} catch (jmesErr) {
|
||||
setError(`JMESPath Error: ${jmesErr.message}`);
|
||||
setResult('');
|
||||
}
|
||||
};
|
||||
|
||||
// Auto-evaluate when inputs change
|
||||
useEffect(() => {
|
||||
if (jmespathExpression && jsonData) {
|
||||
evaluateExpression();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [jmespathExpression, jsonData]);
|
||||
|
||||
const handleJmespathChange = (e) => {
|
||||
setJmespathExpression(e.target.value);
|
||||
};
|
||||
|
||||
const handleJsonChange = (e) => {
|
||||
setJsonData(e.target.value);
|
||||
};
|
||||
|
||||
const formatJson = () => {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonData);
|
||||
setJsonData(JSON.stringify(parsed, null, 2));
|
||||
} catch (err) {
|
||||
// If JSON is invalid, don't format
|
||||
}
|
||||
};
|
||||
|
||||
const clearAll = () => {
|
||||
setJmespathExpression('');
|
||||
setJsonData('');
|
||||
setResult('');
|
||||
setError('');
|
||||
setJsonError('');
|
||||
};
|
||||
|
||||
const loadSample = () => {
|
||||
setJmespathExpression('people[*].name');
|
||||
setJsonData(`{
|
||||
"people": [
|
||||
{
|
||||
"name": "Alice Johnson",
|
||||
"age": 28,
|
||||
"city": "Chicago",
|
||||
"skills": ["JavaScript", "React", "Node.js"]
|
||||
},
|
||||
{
|
||||
"name": "Bob Wilson",
|
||||
"age": 35,
|
||||
"city": "Seattle",
|
||||
"skills": ["Python", "Django", "PostgreSQL"]
|
||||
},
|
||||
{
|
||||
"name": "Carol Davis",
|
||||
"age": 32,
|
||||
"city": "Austin",
|
||||
"skills": ["Java", "Spring", "MySQL"]
|
||||
}
|
||||
],
|
||||
"total": 3,
|
||||
"department": "Engineering"
|
||||
}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container-fluid">
|
||||
{/* Header Section */}
|
||||
<div className="header-section">
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12 text-center">
|
||||
<h1 className="display-4 mb-3">JMESPath Testing Tool</h1>
|
||||
<p className="lead">
|
||||
Validate and test JMESPath expressions against JSON data in real-time.
|
||||
Enter your JMESPath query and JSON data below to see the results instantly.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="container-fluid content-section">
|
||||
<div className="row h-100">
|
||||
{/* JMESPath Expression Input - Middle Section */}
|
||||
<div className="col-12 mb-3">
|
||||
<div className="card">
|
||||
<div className="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 className="mb-0">
|
||||
<i className="bi bi-search me-2"></i>
|
||||
JMESPath Expression
|
||||
</h5>
|
||||
<div>
|
||||
<button
|
||||
className="btn btn-outline-primary btn-sm me-2"
|
||||
onClick={loadSample}
|
||||
title="Load sample data"
|
||||
>
|
||||
Load Sample
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-outline-danger btn-sm"
|
||||
onClick={clearAll}
|
||||
title="Clear all inputs"
|
||||
>
|
||||
Clear All
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<input
|
||||
type="text"
|
||||
className={`form-control jmespath-input ${error ? 'error' : ''}`}
|
||||
value={jmespathExpression}
|
||||
onChange={handleJmespathChange}
|
||||
placeholder="Enter JMESPath expression (e.g., people[*].name)"
|
||||
/>
|
||||
{error && (
|
||||
<div className="alert alert-danger mt-2 mb-0">
|
||||
<small>{error}</small>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Row - JSON Input and Results */}
|
||||
<div className="col-md-6 mb-3">
|
||||
<div className="card h-100">
|
||||
<div className="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 className="mb-0">
|
||||
<i className="bi bi-file-code me-2"></i>
|
||||
JSON Data
|
||||
</h5>
|
||||
<button
|
||||
className="btn btn-outline-secondary btn-sm"
|
||||
onClick={formatJson}
|
||||
title="Format JSON"
|
||||
>
|
||||
Format JSON
|
||||
</button>
|
||||
</div>
|
||||
<div className="card-body input-section">
|
||||
<div className="textarea-container">
|
||||
<textarea
|
||||
className={`form-control json-input ${jsonError ? 'error' : ''}`}
|
||||
value={jsonData}
|
||||
onChange={handleJsonChange}
|
||||
placeholder="Enter JSON data here..."
|
||||
/>
|
||||
{jsonError && (
|
||||
<div className="alert alert-danger mt-2 mb-0">
|
||||
<small>{jsonError}</small>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Results Output - Bottom Right */}
|
||||
<div className="col-md-6 mb-3">
|
||||
<div className="card h-100">
|
||||
<div className="card-header">
|
||||
<h5 className="mb-0">
|
||||
<i className="bi bi-arrow-right-circle me-2"></i>
|
||||
Query Result
|
||||
</h5>
|
||||
</div>
|
||||
<div className="card-body output-section">
|
||||
<div className="textarea-container">
|
||||
<textarea
|
||||
className={`form-control result-output ${result && !error && !jsonError ? 'success' : ''}`}
|
||||
value={result}
|
||||
readOnly
|
||||
placeholder="Results will appear here..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
Reference in New Issue
Block a user