Skip to content

Parsing & Import

Overview

The engine is format-agnosticengine.init({ data }) receives a deserialized BlueprintExport object, not a file or raw string. The engine never reads files and has no dependency on any serialization library.

The LSDE editor exports blueprints in multiple formats:

FormatFull graph?Use case
JSONYesDefault — widest parser support across all platforms
XMLYesXML-based pipelines, localization tools (XLIFF), legacy systems
YAMLYesHuman-readable editing, git-friendly diffs, config-driven workflows
CSVNo (flat)Localization / translation — export to Excel or Google Sheets

CSV exports a flat table of dialogue text by locale. It does not contain connections, conditions, or actions — it cannot be used with the engine runtime.

PlatformJSONXMLYAML
UnityNewtonsoft.Json (com.unity.nuget.newtonsoft-json)System.Xml (native)not recommended
Unreal EngineFJsonSerializer (native module Json)XmlParser (native)UnrealYAML (marketplace)
GodotJSON.parse_string() (native)XMLParser (native)godot-yaml (GDExtension)
TypeScriptJSON.parse() (native)fast-xml-parseryaml
CSharpSystem.Text.Json (.NET 5+) / Newtonsoft.JsonSystem.Xml (native)YamlDotNet
CPPnlohmann/json (header-only)tinyxml2 / pugixmlyaml-cpp

Unity

csharp
// Install: dotnet add package LsdeDialogEngine.Newtonsoft
// Unity Package Manager: com.unity.nuget.newtonsoft-json (auto-pulled)
using LsdeDialogEngine;
using LsdeDialogEngine.Newtonsoft;

var json = File.ReadAllText("blueprint.json");
var blueprint = LsdeJson.Parse(json);
engine.Init(new InitOptions { Data = blueprint });
csharp
// Without companion package — manual converter setup
using Newtonsoft.Json;
using LsdeDialogEngine;

var json = File.ReadAllText("blueprint.json");
var settings = new JsonSerializerSettings();
settings.Converters.Add(new BlueprintBlockNewtonsoftConverter()); // see Polymorphic Dispatch
var blueprint = JsonConvert.DeserializeObject<BlueprintExport>(json, settings);
engine.Init(new InitOptions { Data = blueprint });
csharp
// System.Xml is native — nothing to install
using System.Xml.Linq;
using LsdeDialogEngine;

var doc = XDocument.Load("blueprint.xml");
// Manual mapping from XElement → BlueprintExport required.
// See polymorphic dispatch section below for BlueprintBlock handling.

Unreal Engine

cpp
#include "Json.h"
#include <lsde/engine.h>

FString JsonStr;
FFileHelper::LoadFileToString(JsonStr, TEXT("blueprint.json"));

TSharedPtr<FJsonObject> JsonObject;
auto Reader = TJsonReaderFactory<>::Create(JsonStr);
FJsonSerializer::Deserialize(Reader, JsonObject);

// Map FJsonObject → BlueprintExport manually.
// Dispatch on block "type" field for polymorphism.
cpp
#include "XmlParser.h"

FXmlFile XmlFile(TEXT("blueprint.xml"));
auto* Root = XmlFile.GetRootNode();
// Walk XML nodes → map to BlueprintExport.

Godot

gdscript
var file = FileAccess.open("res://blueprint.json", FileAccess.READ)
var data = JSON.parse_string(file.get_as_text())
file.close()

engine.init({"data": data})
# No polymorphism issues — GDScript uses dynamic Dictionaries.
gdscript
var parser = XMLParser.new()
parser.open("res://blueprint.xml")
# Walk parser events → build Dictionary matching BlueprintExport structure.
# See Godot docs: XMLParser class reference.

TypeScript (TS/JS)

ts
// Bundlers (Vite, Webpack, esbuild) auto-parse .json imports.
import blueprintJson from './blueprint.json';
engine.init({ data: blueprintJson });
ts
const json = fs.readFileSync('./blueprint.json', 'utf-8');
engine.init({ data: JSON.parse(json) });
// No polymorphism issues — JS objects are dynamically typed.
ts
// npm install fast-xml-parser
import { XMLParser } from 'fast-xml-parser';
const xml = fs.readFileSync('./blueprint.xml', 'utf-8');
const parser = new XMLParser({ ignoreAttributes: false });
const data = parser.parse(xml);
engine.init({ data });
ts
// npm install yaml
import { parse } from 'yaml';
const yml = fs.readFileSync('./blueprint.yaml', 'utf-8');
engine.init({ data: parse(yml) });

CSharp (C#)

csharp
// Install: dotnet add package LsdeDialogEngine.SystemTextJson
using LsdeDialogEngine;
using LsdeDialogEngine.Json;

var json = File.ReadAllText("blueprint.json");
var blueprint = LsdeJson.Parse(json);
engine.Init(new InitOptions { Data = blueprint });
csharp
// Without companion package — manual converter setup
using System.Text.Json;
using System.Text.Json.Serialization;
using LsdeDialogEngine;

var json = File.ReadAllText("blueprint.json");
var options = new JsonSerializerOptions {
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    Converters = {
        new JsonStringEnumConverter(),
        new BlueprintBlockConverter(),       // see Polymorphic Dispatch
        new BlockPropertyValueConverter(),
    },
};
var blueprint = JsonSerializer.Deserialize<BlueprintExport>(json, options);
engine.Init(new InitOptions { Data = blueprint });
csharp
// System.Xml is included in .NET — nothing to install.
using System.Xml.Linq;
using LsdeDialogEngine;

var doc = XDocument.Load("blueprint.xml");
// Manual mapping from XElement → BlueprintExport required.
csharp
// dotnet add package YamlDotNet
using YamlDotNet.Serialization;
using LsdeDialogEngine;

var yaml = File.ReadAllText("blueprint.yaml");
var deserializer = new DeserializerBuilder().Build();
// YamlDotNet requires custom type converters for polymorphic blocks.

CPP (C++)

cpp
// Include the optional JSON loader (requires nlohmann/json)
#include <lsde/json_loader.h>

auto blueprint = lsde::LsdeJson::parseFile("blueprint.json");
// or from string:
// auto blueprint = lsde::LsdeJson::parse(jsonString);
engine.init({blueprint});
cpp
// Without json_loader.h — manual polymorphic dispatch
#include <nlohmann/json.hpp>
#include <lsde/engine.h>

std::ifstream f("blueprint.json");
auto j = nlohmann::json::parse(f);
auto blueprint = j.get<lsde::BlueprintExport>();
// Requires custom from_json — see polymorphic dispatch below.
cpp
#include <tinyxml2.h>
tinyxml2::XMLDocument doc;
doc.LoadFile("blueprint.xml");
// Walk XML elements → map to BlueprintExport.
cpp
// Install: apt install libyaml-cpp-dev (or include source)
#include <yaml-cpp/yaml.h>
auto node = YAML::LoadFile("blueprint.yaml");
// Requires custom YAML::convert specializations.

Polymorphic Dispatch

BlueprintScene.blocks is an array of BlueprintBlock — a discriminated union with 5 subtypes identified by the type field:

typeSubtypeSpecific fields
DIALOGDialogBlockdialogueText, content, structureKey
CHOICEChoiceBlockchoices
CONDITIONConditionBlockconditions
ACTIONActionBlockactions
NOTENoteBlock(none)

Dynamically-typed languages (TypeScript, GDScript) handle this automatically — parsed objects already contain all fields.

Statically-typed languages (C#, C++) need a custom converter that reads the type field and constructs the correct subtype. Without it, subtype-specific fields like dialogueText or choices are silently lost.

Companion packages

If you use LsdeDialogEngine.Newtonsoft or LsdeDialogEngine.SystemTextJson, these converters are already included — just call LsdeJson.Parse(json). The code below is for manual integration only.

CSharp — Newtonsoft.Json (Unity)

csharp
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using LsdeDialogEngine;

class BlueprintBlockNewtonsoftConverter : JsonConverter<BlueprintBlock>
{
    public override BlueprintBlock ReadJson(JsonReader reader, Type objectType,
        BlueprintBlock existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var obj = JObject.Load(reader);
        var type = obj["type"]?.ToString();
        BlueprintBlock block = type switch
        {
            "DIALOG"    => new DialogBlock(),
            "CHOICE"    => new ChoiceBlock(),
            "CONDITION" => new ConditionBlock(),
            "ACTION"    => new ActionBlock(),
            "NOTE"      => new NoteBlock(),
            _           => throw new JsonException($"Unknown block type: {type}")
        };
        serializer.Populate(obj.CreateReader(), block);
        return block;
    }

    public override void WriteJson(JsonWriter writer, BlueprintBlock value, JsonSerializer serializer)
        => serializer.Serialize(writer, value, value.GetType());
}

CSharp — System.Text.Json (.NET 5+)

csharp
using System.Text.Json;
using System.Text.Json.Serialization;
using LsdeDialogEngine;

class BlueprintBlockConverter : JsonConverter<BlueprintBlock>
{
    public override BlueprintBlock Read(ref Utf8JsonReader reader, Type typeToConvert,
        JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;
        var type = root.GetProperty("type").GetString();
        var json = root.GetRawText();
        return type switch
        {
            "DIALOG"    => JsonSerializer.Deserialize<DialogBlock>(json, options)!,
            "CHOICE"    => JsonSerializer.Deserialize<ChoiceBlock>(json, options)!,
            "CONDITION" => JsonSerializer.Deserialize<ConditionBlock>(json, options)!,
            "ACTION"    => JsonSerializer.Deserialize<ActionBlock>(json, options)!,
            "NOTE"      => JsonSerializer.Deserialize<NoteBlock>(json, options)!,
            _           => throw new JsonException($"Unknown block type: {type}")
        };
    }

    public override void Write(Utf8JsonWriter writer, BlueprintBlock value,
        JsonSerializerOptions options)
        => JsonSerializer.Serialize(writer, value, value.GetType(), options);
}

class BlockPropertyValueConverter : JsonConverter<object>
{
    public override object Read(ref Utf8JsonReader reader, Type typeToConvert,
        JsonSerializerOptions options)
    {
        return reader.TokenType switch
        {
            JsonTokenType.String => reader.GetString(),
            JsonTokenType.Number => reader.TryGetInt64(out var l) ? (object)(double)l : reader.GetDouble(),
            JsonTokenType.True   => true,
            JsonTokenType.False  => false,
            JsonTokenType.Null   => null,
            _                    => throw new JsonException($"Unexpected token {reader.TokenType}")
        };
    }

    public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
        => JsonSerializer.Serialize(writer, value, options);
}

CPP — nlohmann/json

cpp
#include <nlohmann/json.hpp>
#include <lsde/types.h>

void from_json(const nlohmann::json& j, std::unique_ptr<lsde::BlueprintBlock>& block) {
    auto type = j.at("type").get<std::string>();
    if      (type == "DIALOG")    block = std::make_unique<lsde::DialogBlock>();
    else if (type == "CHOICE")    block = std::make_unique<lsde::ChoiceBlock>();
    else if (type == "CONDITION") block = std::make_unique<lsde::ConditionBlock>();
    else if (type == "ACTION")    block = std::make_unique<lsde::ActionBlock>();
    else if (type == "NOTE")      block = std::make_unique<lsde::NoteBlock>();
    else throw std::runtime_error("Unknown block type: " + type);
    j.get_to(*block);
}