| title | sidebar_label | sidebar_position | description |
|---|---|---|---|
Schema Checker - Version 3 |
Schema Checker |
2 |
Validate Morphir IR JSON against the Version 3 schema |
import React from "react"; import JsonView from "@uiw/react-json-view"; import { githubDarkTheme } from "@uiw/react-json-view/githubDark"; import { githubLightTheme } from "@uiw/react-json-view/githubLight"; import Editor from "@monaco-editor/react"; import { useColorMode } from "@docusaurus/theme-common"; import Ajv from "ajv"; import addFormats from "ajv-formats";
Validate your Morphir IR JSON against the Version 3 (Stable) schema. Version 3 is the current production format with capitalized tags.
export const SchemaChecker = () => { const [jsonInput, setJsonInput] = React.useState(''); const [validationResult, setValidationResult] = React.useState(null); const [isValidating, setIsValidating] = React.useState(false); const [schema, setSchema] = React.useState(null); const [loadError, setLoadError] = React.useState(null); const { colorMode } = useColorMode(); const fileInputRef = React.useRef(null);
React.useEffect(() => {
fetch('/schemas/morphir-ir-v3.json')
.then(r => r.ok ? r.json() : Promise.reject(HTTP ${r.status}))
.then(setSchema)
.catch(err => setLoadError(Failed to load schema: ${err}));
}, []);
const handleFileUpload = (event) => { const file = event.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (e) => { setJsonInput(e.target.result); setValidationResult(null); }; reader.readAsText(file); } };
const validateJson = async () => { setIsValidating(true); setValidationResult(null);
try {
let parsedJson;
try {
parsedJson = JSON.parse(jsonInput);
} catch (parseErr) {
setValidationResult({
valid: false,
errors: [{ message: `JSON Parse Error: ${parseErr.message}` }],
parsedJson: null,
});
setIsValidating(false);
return;
}
if (!schema) {
setValidationResult({
valid: false,
errors: [{ message: 'Schema not loaded' }],
parsedJson,
});
setIsValidating(false);
return;
}
const ajv = new Ajv({ allErrors: true, verbose: true, strict: false });
addFormats(ajv);
const validate = ajv.compile(schema);
const valid = validate(parsedJson);
setValidationResult({
valid,
errors: validate.errors || [],
parsedJson,
});
} catch (err) {
setValidationResult({
valid: false,
errors: [{ message: `Validation Error: ${err.message}` }],
parsedJson: null,
});
}
setIsValidating(false);
};
const sampleJson = [ "Library", [["my", "org"], ["my", "package"]], {}, { "modules": [ [ [["example"], ["module"]], { "access": "Public", "value": { "types": [], "values": [] } } ] ] } ];
if (loadError) { return
return (
<div style={{ marginBottom: '1rem' }}>
<label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: 'bold' }}>
Morphir IR JSON (Monaco Editor):
</label>
<div style={{ border: '1px solid var(--ifm-color-emphasis-300)', borderRadius: '4px' }}>
<Editor
height="350px"
language="json"
value={jsonInput}
onChange={(value) => {
setJsonInput(value || '');
setValidationResult(null);
}}
theme={colorMode === 'dark' ? 'vs-dark' : 'light'}
options={{
minimap: { enabled: true },
lineNumbers: 'on',
scrollBeyondLastLine: false,
wordWrap: 'on',
automaticLayout: true,
fontSize: 14,
folding: true,
formatOnPaste: true,
tabSize: 2,
}}
/>
</div>
</div>
<div style={{ marginBottom: '1rem' }}>
<button
onClick={validateJson}
disabled={isValidating || !jsonInput.trim() || !schema}
style={{
padding: '0.75rem 2rem',
cursor: isValidating || !jsonInput.trim() || !schema ? 'not-allowed' : 'pointer',
border: 'none',
borderRadius: '4px',
backgroundColor: isValidating || !jsonInput.trim() || !schema
? 'var(--ifm-color-emphasis-300)'
: 'var(--ifm-color-primary)',
color: 'white',
fontWeight: 'bold',
fontSize: '1rem',
}}
>
{isValidating ? 'Validating...' : 'Validate against V3 Schema'}
</button>
</div>
{validationResult && (
<div>
{validationResult.valid ? (
<div className="alert alert--success" style={{ marginBottom: '1rem' }}>
<strong>Valid!</strong> Your JSON conforms to the Morphir IR v3 schema.
</div>
) : (
<div className="alert alert--danger" style={{ marginBottom: '1rem' }}>
<strong>Invalid!</strong> Found {validationResult.errors.length} error(s):
<ul style={{ marginTop: '0.5rem', marginBottom: 0 }}>
{validationResult.errors.slice(0, 10).map((err, i) => (
<li key={i} style={{ fontFamily: 'monospace', fontSize: '0.9rem' }}>
{err.instancePath && <strong>{err.instancePath}: </strong>}
{err.message}
</li>
))}
{validationResult.errors.length > 10 && (
<li>...and {validationResult.errors.length - 10} more errors</li>
)}
</ul>
</div>
)}
{validationResult.parsedJson && (
<details>
<summary style={{ cursor: 'pointer', fontWeight: 'bold', marginBottom: '0.5rem' }}>
Parsed JSON Tree
</summary>
<JsonView
value={validationResult.parsedJson}
style={colorMode === 'dark' ? githubDarkTheme : githubLightTheme}
displayDataTypes={false}
collapsed={2}
/>
</details>
)}
</div>
)}
</div>
); };
Version 3 uses tagged arrays with capitalized tags:
["Library", packageName, dependencies, definition]
["Variable", attributes, name]
["Reference", attributes, fqName, typeArgs]- Tagged array format:
["TagName", ...args] - Capitalized tags:
Library,Variable,Reference - Current production format: Used by morphir-elm
- Schema Viewer - Interactive schema browser with LCR example
- Download Schema - JSON format
- Global Schema Checker - Check all versions
- Migration Guide - Version migration
- LCR Interactive - Real-world example