Edifact.Projection 1.0.0-preview.6

This is a prerelease version of Edifact.Projection.
dotnet add package Edifact.Projection --version 1.0.0-preview.6
                    
NuGet\Install-Package Edifact.Projection -Version 1.0.0-preview.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Edifact.Projection" Version="1.0.0-preview.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Edifact.Projection" Version="1.0.0-preview.6" />
                    
Directory.Packages.props
<PackageReference Include="Edifact.Projection" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Edifact.Projection --version 1.0.0-preview.6
                    
#r "nuget: Edifact.Projection, 1.0.0-preview.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Edifact.Projection@1.0.0-preview.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Edifact.Projection&version=1.0.0-preview.6&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Edifact.Projection&version=1.0.0-preview.6&prerelease
                    
Install as a Cake Tool

Edifact.Projection

Projects a matched message into JSON or XML, either as the document it describes or as a linked form in which every value still points at the directory definition it was read against.

Two different projections, for two different jobs:

  • MessageDocument — one message as data, for anything that consumes it: a mapper, a queue, an API response. It is lossless, and turning it back into the interchange it came from gives the same characters.
  • LinkedMessage — a message type and everything it names: 42 segments, 63 composites, 201 elements and 101 code lists for D.96A INVOIC, gathered in one document so a form builder does one fetch instead of walking a graph five levels deep.

Install

dotnet add package Edifact.Projection --prerelease

net8.0 and net10.0, no external dependencies.

You supply the directory

No directory data ships in this package. A compiled pack is a derivative of the UN Directory, and shipping one would make every consumer a redistributor of it. Download a release from UNECE (https://unece.org/trade/uncefact/unedifact/download) and ingest it once:

dotnet tool install --global Edifact.Cli --prerelease
edifact ingest ~/Downloads/D96A --out ~/edifact/packs/compiled

That writes the pack to ~/edifact/packs/compiled/untdid-d96a, and puts the four ISO 9735 syntax definitions in ~/edifact/packs/syntax beside it. Those four are the one input no ingestion can produce — the UNTDID omits the service definitions — so they reach a machine only because the tool ships them. Files already in that directory are left alone.

A message as a document, and back

using Edifact.Core.Syntax;
using Edifact.Projection;
using Edifact.Projection.Serialization;
using Edifact.Schema.Serialization;
using Edifact.Validation;

var syntax = new SyntaxPackSet("/home/me/edifact/packs/syntax");
var pack = PackReader.Read("/home/me/edifact/packs/compiled/untdid-d96a", syntax.For);

var text = File.ReadAllText("invoice.edi");
var tokens = EdifactTokenizer.Tokenize(text);
var report = new EdifactValidator(pack, syntax.For).Validate(tokens);

// One document per message. The syntax argument is what lets the interchange be rebuilt exactly;
// the pack is optional and names the elements.
var document = MessageProjection.ToDocument(report.Trees[0], tokens.Syntax, pack);

File.WriteAllText("invoice.json", ProjectionJson.Serialise(document));
File.WriteAllText("invoice.xml", ProjectionXml.Serialise(document));

// And back — the property this package is built around.
var read = ProjectionJson.Deserialise(File.ReadAllText("invoice.json"), "invoice.json");
var rebuilt = EdifactWriter.Write(MessageProjection.ToSegments(read), tokens.Syntax);

// MessageProjection.ToTree(read, pack) puts the message tree back, for walking it again.

ToSegments needs no directory and no message definition: writing an interchange back out is a question about characters, and the one caller who most often has neither — an inspector showing somebody the file they sent — still has to be able to do it.

A MessageDocument that names a message type the directory does not define still round-trips; its segments come back as orphans rather than as an error. ProjectionJson.Deserialise throws ProjectionFormatException for a document that is not one.

A message type, linked

using Edifact.Projection;
using Edifact.Projection.Serialization;
using Edifact.Schema.Model;

var linked = LinkedMessageProjection.Gather(pack, new MessageKey("INVOIC", "D", "96A"));

Console.WriteLine(LinkedMessageJson.Serialise(linked));

// With a trading partner's guide applied, so a builder never offers a field the agreement forbids:
// var linked = LinkedMessageProjection.Gather(effective);   // an Edifact.Overlays EffectiveMessage

The guided form carries the restrictions as data — which positions are excluded, which code lists were narrowed and by whom — rather than silently presenting a narrowed directory as the directory.

The constraint everything else follows from

A projection that cannot be turned back into the interchange it came from is a report, not a projection. So the property held under test is not "the JSON looks right", it is:

text → tokenize → match → tree → document → JSON → document → tree → write  ==  text

character for character, over 2000 generated invoices. Looking right is exactly what a projection that has silently dropped a trailing empty element does.

Where this sits

Edifact.Projection → Edifact.Overlays, Edifact.Structure. It needs a MessageTree, which normally comes from Edifact.Validation or from StructureMatcher directly.

The design notes are in DESIGN.md. Full documentation: https://github.com/101-semaphore/EDIFACT.

Licence

Apache-2.0. See the NOTICE in this package for what the wider project is derived from and under what terms.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-preview.6 55 10/11/2026
1.0.0-preview.5 72 9/19/2026
1.0.0-preview.4 70 9/17/2026
1.0.0-preview.3 97 9/7/2026
1.0.0-preview.2 88 9/6/2026
1.0.0-preview.1 83 9/6/2026