Skip to content

Add OnUnresolvedSubtype callback to detect unregistered subtypes (#112) - #193

Open
manuc66 wants to merge 4 commits into
masterfrom
feature/error-paths-in-exceptions
Open

Add OnUnresolvedSubtype callback to detect unregistered subtypes (#112)#193
manuc66 wants to merge 4 commits into
masterfrom
feature/error-paths-in-exceptions

Conversation

@manuc66

@manuc66 manuc66 commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Closes #112

Problem

The reporter of #112 wants to detect, while deserializing a polymorphic tree, every object whose Type discriminator is not registered — without throwing on the first mismatch. Today the only way is a "trap" fallback type: its constructor records each unknown Type into a static list, which is not thread-safe and requires cleanup after deserialization.

Fix

Adds OnUnresolvedSubtype to all four builders (JsonSubtypesConverterBuilder / JsonSubtypesWithPropertyConverterBuilder, in both JsonSubTypes and JsonSubTypes.Text.Json). The callback fires once per JSON element whose subtype cannot be resolved: unknown or missing discriminator value, or no matching property in property-presence mode.

The hook sits at the existing single failure point in both backends (resolvedType ?? GetFallbackSubType(...)), so nothing changes when no callback is registered. UnresolvedSubtypeInfo exposes the parent type, the discriminator name and value, a HasDiscriminator flag (to distinguish a missing discriminator from an unknown value, both otherwise read as null) and the fallback subtype that will be used (null when none is configured).

Tests

  • JsonSubTypes.Text.Json.Tests: 139 pass on net8.0 and net10.0. Six new tests: no callback when the subtype resolves, unknown value, missing discriminator, no fallback configured, one callback per unresolved element in a nested tree, property-presence mode.
  • JsonSubTypes.Tests (net46): compiles, but the NUnit suite cannot execute under Linux/VSTest, so I validated the same six scenarios through a net8.0 harness against the netstandard2.0 build (all pass).

Honest notes

  • The callback runs on the deserializing thread. A converter shared across threads calls it from several threads, so the callback must be thread-safe; I did not add locking or weak-event machinery.
  • JsonPath is available in the Newtonsoft backend but not in System.Text.Json (resolution works on a JsonDocument, which carries no path), so I omitted it from the info type.
  • The callback cannot override the resolved type. That would be a separate custom-type-resolver feature; say so here if you actually need it.

Feedback welcome on the API shape (method name, and what UnresolvedSubtypeInfo exposes).

Fires once per JSON element whose subtype cannot be resolved (unknown or
missing discriminator value, or no matching property in property-presence
mode), on both the Newtonsoft.Json and System.Text.Json backends. The
callback receives the parent type, discriminator name/value, whether the
discriminator was present, and the fallback subtype that will be used.

Extends the existing fallback point in ResolveType/GetType so no behavior
changes when no callback is registered. #112
Covers resolved subtype (no callback), unknown discriminator value, missing
discriminator, no configured fallback, one callback per unresolved element in
a nested tree, and property-presence mode. #112
…olvedSubtypeInfo

The public API keeps the README as its documentation; no XML doc comments on
fluent builder methods or value classes, consistent with the rest of the repo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detect all unregistered subtypes for a given json?

1 participant