Currently, Jedison only provides a top-level setValue method that recursively walks the entire schema tree to apply values. For schemas with multiple nested anyOf combinators, this can cause significant performance overhead, especially in arrays or tables with many rows, because every node is evaluated recursively, even when only a single node needs updating.
Could there be a per-node setValue method that allows updating a specific node directly? This would avoid full recursion, skip unnecessary anyOf evaluations, and improve both speed and memory usage when importing or updating large datasets.
Hopefully, this example demonstrates the issue.
<!DOCTYPE html>
<html data-bs-theme="auto">
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jedison@latest/dist/umd/jedison.umd.js"></script>
</head>
<body>
<div class="container">
<h2 class="mt-5">Jedison Performance Test</h2>
<div class="mt-3" id="jedison-container-slow"></div>
<div class="mt-5" id="jedison-container-fast"></div>
</div>
<script>
// Generate 300 sample observations with targets and apollo
const sampleObservations = Array.from({ length: 300 }, (_, i) => ({
observer: `Observer ${i+1}`,
location: `Location ${i+1}`,
date: new Date(2026, 3, (i % 28) + 1).toISOString().split('T')[0],
targets: i % 2 === 0
? { type: "PlantTarget", species: `Plant Species ${i+1}`, count: Math.floor(Math.random() * 20) }
: { type: "AnimalTarget", species: `Animal Species ${i+1}`, behavior: "Active" },
apollo: i % 3 === 0
? { version: "v1", notes: "Apollo test 1" }
: { version: "v2", notes: "Apollo test 2", extra: "Extra info" }
}));
// ----------- Version A: with second anyOf (slow) -----------------
console.time("load-with-anyof");
const jedisonSlow = new Jedison.Create({
container: document.querySelector('#jedison-container-slow'),
theme: new Jedison.ThemeBootstrap5(),
schema: {
"title": "UW observation (with apollo anyOf)",
"type": "object",
"properties": {
"project": { "type": "string", "description": "Project name" },
"observations": {
"type": "array",
"title": "Observations",
"default": sampleObservations,
"items": {
"type": "object",
"properties": {
"observer": { "type": "string" },
"location": { "type": "string" },
"date": { "type": "string", "format": "date" },
"targets": {
"type": "object",
"anyOf": [
{
"title": "PlantTarget",
"type": "object",
"properties": {
"type": { "const": "PlantTarget" },
"species": { "type": "string" },
"count": { "type": "integer", "minimum": 0 }
},
"required": ["type","species","count"]
},
{
"title": "AnimalTarget",
"type": "object",
"properties": {
"type": { "const": "AnimalTarget" },
"species": { "type": "string" },
"behavior": { "type": "string" }
},
"required": ["type","species","behavior"]
}
]
},
"apollo": {
"anyOf": [
{
"title": "Apollo v1",
"type": "object",
"properties": {
"version": { "const": "v1" },
"notes": { "type": "string" }
},
"required": ["version","notes"]
},
{
"title": "Apollo v2",
"type": "object",
"properties": {
"version": { "const": "v2" },
"notes": { "type": "string" },
"extra": { "type": "string" }
},
"required": ["version","notes"]
}
]
}
},
"required": ["observer","location","date","targets","apollo"]
}
}
}
}
});
console.timeEnd("load-with-anyof");
// ----------- Version B: remove second anyOf (fast) -----------------
console.time("load-without-anyof");
const jedisonFast = new Jedison.Create({
container: document.querySelector('#jedison-container-fast'),
theme: new Jedison.ThemeBootstrap5(),
schema: {
"title": "UW observation (apollo single schema)",
"type": "object",
"properties": {
"project": { "type": "string", "description": "Project name" },
"observations": {
"type": "array",
"title": "Observations",
"default": sampleObservations,
"items": {
"type": "object",
"properties": {
"observer": { "type": "string" },
"location": { "type": "string" },
"date": { "type": "string", "format": "date" },
"targets": {
"type": "object",
"anyOf": [
{
"title": "PlantTarget",
"type": "object",
"properties": {
"type": { "const": "PlantTarget" },
"species": { "type": "string" },
"count": { "type": "integer", "minimum": 0 }
},
"required": ["type","species","count"]
},
{
"title": "AnimalTarget",
"type": "object",
"properties": {
"type": { "const": "AnimalTarget" },
"species": { "type": "string" },
"behavior": { "type": "string" }
},
"required": ["type","species","behavior"]
}
]
},
"apollo": {
"title": "Apollo",
"type": "object",
"properties": {
"version": { "type": "string" },
"notes": { "type": "string" }
},
"required": ["version","notes"]
}
},
"required": ["observer","location","date","targets","apollo"]
}
}
}
}
});
console.timeEnd("load-without-anyof");
</script>
</body>
</html>
Currently, Jedison only provides a top-level setValue method that recursively walks the entire schema tree to apply values. For schemas with multiple nested anyOf combinators, this can cause significant performance overhead, especially in arrays or tables with many rows, because every node is evaluated recursively, even when only a single node needs updating.
Could there be a per-node setValue method that allows updating a specific node directly? This would avoid full recursion, skip unnecessary anyOf evaluations, and improve both speed and memory usage when importing or updating large datasets.
Hopefully, this example demonstrates the issue.