Skip to content

Runtime schema generation for types (XSD, BSD, JSON Schema) + PubSub message schemas#3916

Closed
marcschier wants to merge 2 commits into
part14pubsubfrom
part14experimental
Closed

Runtime schema generation for types (XSD, BSD, JSON Schema) + PubSub message schemas#3916
marcschier wants to merge 2 commits into
part14pubsubfrom
part14experimental

Conversation

@marcschier

@marcschier marcschier commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds runtime schema generation for OPC UA data types so generated encodeable types and dynamically-added complex types can expose their schemas in every supported encoding. Stacked on the OPC UA Part 14 (PubSub) work and targets the part14pubsub branch (#3892).

Two new trimmable, NativeAOT-compatible libraries:

  • Stack/Opc.Ua.Core.Schema — injectable ISchemaProvider via services.AddOpcUa().AddSchemaGeneration() (direct construction also supported). Generators, each per-type and per-namespace (with per-namespace $ref/import resolution across namespaces):
    • JSON Schema (Part 6 Annex C, draft 2020-12) — compact + verbose, faithful to the stack JsonEncoder (Int64/UInt64 → string, ByteString → base64, Float/Double → number|string, standard built-ins emitted once in $defs, unions, enums, value ranks, $ref dependency closure, and the compact SwitchField / EncodingMask members).
    • XSD — in-box System.Xml.Schema.XmlSchema object model, per-namespace xs:import.
    • BSD (OPC Binary, Part 6) — existing Opc.Ua.Schema.Binary object model serialized via a direct XmlWriter; optional-field structs use the leading 32-bit EncodingMask, unions use SwitchField, per-namespace opc:Import.
    • Resolver model: IDataTypeDefinitionResolver, in-memory DataTypeDefinitionRegistry, EncodeableFactoryDefinitionSource (reads definitions exposed by the encodeable factory) and CompositeDataTypeDefinitionResolver; thin extension API (GetXmlSchema / GetBinarySchema / GetJsonSchema / TryGetJsonSchema).
  • Libraries/Opc.Ua.PubSub.SchemaAddPubSubSchema()IPubSubSchemaProvider: per-DataSet field schemas built from DataSetMetaDataType / FieldMetaData honoring DataSetFieldContentMask, plus ua-data NetworkMessage / DataSetMessage / ua-metadata envelope schemas parameterized by the JSON content masks.

Types expose their own schemas (no manual registration required): a new IDataTypeDefinitionSource is implemented by the encodeable activators; the source generator emits a GetDataTypeDefinition override on generated data types; ComplexTypeSystem.RegisterDataTypeDefinitions(...) mirrors dynamically-built complex types; and a server-side RegisterDataTypeSchemasAsync(...) registers address-space DataType nodes.

Schemas are built in code as strongly-typed object models (no embedded schema strings), so unused generation paths trim away. Shipping code uses in-box models only — no XmlSerializer, no XmlSchema.Write, no generic JsonArray.Add<T>. JsonSchema.Net is a test-only dependency used to validate the generated schemas against real encoded OPC UA JSON.

Documentation: Docs/SchemaGeneration.md (linked from Docs/README.md).

Verification

  • The whole UA.slnx solution builds with 0 warnings on net10.0; the changed libraries also build clean on net48 and netstandard2.1.
  • Tests pass (net10.0): Opc.Ua.Core.Schema.Tests 64, Opc.Ua.PubSub.Schema.Tests 23, Opc.Ua.Client.ComplexTypes.Tests 2729, Opc.Ua.Server.Tests 1894, Opc.Ua.Core.Tests 3276, Opc.Ua.Types.Tests 7570, Opc.Ua.SourceGeneration.Core.Tests 3653, plus NativeAOT smoke tests in Opc.Ua.Aot.Tests (a published AOT binary was exercised).

Notes

  • Both packages are added to the pack solution (UA Core Library.slnx); Opc.Ua.Core.Schema is a standalone/optional package (not a forced dependency of the Opc.Ua meta-package), matching how the PubSub packages ship.
  • Known minor follow-up: ValueRanks.Any JSON is modeled as scalar-or-array (multi-dimensional arrays are accepted but not dimension-constrained).

Related Issues

Stacked on and targets the OPC UA Part 14 (PubSub) branch — #3892.

Checklist

Put an x in the boxes that apply. You can complete these step by step after opening the PR.

  • I have signed the CLA and read the CONTRIBUTING doc.
  • I have added tests that prove my fix is effective or that my feature works and increased code coverage.
  • I have added all necessary documentation.
  • I have verified that my changes do not introduce (new) build or analyzer warnings.
  • I ran all tests locally using the UA.slnx solution against at least .net framework and .net 10, and all passed.
  • I fixed all failing and flaky tests in the CI pipelines and all CodeQL warnings.
  • I have addressed all PR feedback received.

…ubSub messages

New Opc.Ua.Core.Schema and Opc.Ua.PubSub.Schema libraries that generate XSD, OPC Binary (BSD) and JSON Schema (Part 6 Annex C, compact + verbose) for generated encodeable types and dynamically added complex types, plus PubSub JSON message-format schemas. Schemas are built as object models in code (trimmable, NativeAOT compatible). Includes ISchemaProvider/IPubSubSchemaProvider DI surface, resolver registry, docs and tests.
…n, packaging

Cross-namespace correctness (qualified JSON \ keys; per-namespace XSD/BSD imports) and ValueRanks.Any array modeling. Auto-wiring so types expose their schemas: IDataTypeDefinitionSource on the encodeable activators with a factory-backed resolver, the source generator emitting the definition accessor on generated types, ComplexTypeSystem and server address-space registration helpers. XSD/BSD output validation tests, PubSub coverage and real-message validation, and both new packages added to the pack solution.
marcschier added a commit that referenced this pull request Jun 29, 2026
…uash #3916)

Squash-merge of PR #3916 (head part14experimental) into part14pubsub (#3892).
marcschier added a commit that referenced this pull request Jun 29, 2026
Apply whitespace + style + safe analyzer fixes to the files introduced by the
#3915 (Ethernet L2 transport) and #3916 (runtime schema generation) squash
merges. Removed low-value empty <exception> auto-tags (RCS1140) and restored
the two platform-#if Ethernet channel files (AfPacket/Bpf) that dotnet format
cannot process across TFMs without emitting "Unmerged change" markers.

No behavioural changes; UA.slnx builds 0-warning on net10.0 and the new
project test suites pass.
@marcschier

Copy link
Copy Markdown
Collaborator Author

Squash-merged into part14pubsub (#3892) as commit ddc11c5.

@marcschier marcschier closed this Jun 29, 2026
marcschier added a commit that referenced this pull request Jun 29, 2026
#3916 added a ProjectReference from Opc.Ua.Server to the new
Stack/Opc.Ua.Core.Schema project, but the ConsoleReferenceServer Dockerfile's
per-project restore layer did not copy that csproj, so `dotnet restore`
skipped it and `dotnet publish` failed with NETSDK1004 (assets file not
found). Add the missing COPY line for Opc.Ua.Core.Schema.csproj.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant