Skip to main content

Score to JSON and back

Persist a user-authored arrangement in your database so they can pick it up on any device. Embed a score directly inside a static HTML page โ€” no extra HTTP request, no binary parsing. Ship a Score from a Web Worker to the main thread. Diff two versions of a piece in a text editor to see what a collaborator changed. JsonConverter turns the alphaTab Score object graph into a plain, cycle-free JavaScript object โ€” and back.

The score above is a live Score instance. Pass it through JsonConverter.scoreToJsObject(...) and you get a nested Map structure ready for JSON.stringify.

Round-trip in codeโ€‹

import * as alphaTab from '@coderline/alphatab';

const container = getAlphaTabContainer();
const api = new alphaTab.AlphaTabApi(container, {
core: { file: '/scores/song.gp' },
});

api.scoreLoaded.on(() => {
// Serialize
const jsObject = alphaTab.model.JsonConverter.scoreToJsObject(api.score);
const jsonString = JSON.stringify(jsObject, (_, v) => {
if (v instanceof Map) return Object.fromEntries(v);
if (ArrayBuffer.isView(v)) return Array.from(v);
return v;
});
localStorage.setItem('alphaTab.score', jsonString);

// Deserialize
const stored = localStorage.getItem('alphaTab.score');
if (stored) {
const restored = alphaTab.model.JsonConverter.jsObjectToScore(JSON.parse(stored));
api.renderScore(restored);
}
});

getAlphaTabContainer() is the platform-specific render target.

On Web the short form JsonConverter.scoreToJson(score) / JsonConverter.jsonToScore(jsonString) skips the manual JSON.stringify step and applies the correct Map and typed-array replacer for you. Reach for scoreToJsObject / jsObjectToScore when you want the intermediate JavaScript object โ€” for example to post it to a Web Worker with structuredClone semantics, or to store it in IndexedDB without an intermediate string.

What survives the round-tripโ€‹

scoreToJsObject walks every level of the model โ€” score metadata, tracks, staves, bars, voices, beats, notes โ€” and emits a plain object per node with:

  • All primitive and enum properties (durations, pitches, fret numbers, effect flags).
  • Style containers (ScoreStyle, TrackStyle, and so on) with their color maps.
  • Playback information, tuning, chord definitions, and lyric assignments.
  • Backing-track metadata (the raw audio buffer is included as a byte array).

jsObjectToScore reconstructs the graph and calls Score.finish(settings) to relink parent references, rebuild caches, and validate durations. Pass a Settings instance if you want the reconstruction to apply your project's notation flags; omit it to accept defaults.

Use casesโ€‹

  • Persistent storage โ€” store user-authored scores in your database as JSON, hand them back to alphaTab on load.
  • Web-Worker offloading โ€” build a Score in a worker, transfer the JS object to the main thread, render it there.
  • Diff and version control โ€” the deterministic JSON output diffs cleanly, so score changes show up in a text-oriented workflow.

Where to look nextโ€‹

  • Settings to JSON โ€” the sibling call for Settings.
  • Export to alphaTex โ€” a human-readable text format for the same model.
  • api.renderScore โ€” hand the deserialized Score back to the renderer.
  • JsonConverter in the API reference โ€” the methods scoreToJson, jsonToScore, and scoreToJsObject live here.