Add JSON validation output and interop presentation model#6183
Add JSON validation output and interop presentation model#6183JohnMcPMS merged 2 commits intomicrosoft:masterfrom
Conversation
This comment was marked as spam.
This comment was marked as spam.
| { | ||
| try | ||
| { | ||
| using var doc = JsonDocument.Parse(json); |
There was a problem hiding this comment.
Is there a reason why not using JsonSerializer.Deserialize with some private class or ManifestDiagnostic?
There was a problem hiding this comment.
Tokens already paid, so here is the 🤖 reasoning:
Manual TryGetProperty vs. JsonSerializer.Deserialize<T> — Trade-offs
In favor of the current approach (manual TryGetProperty)
Explicit field-level defaults.
Each TryGetProperty line specifies its own fallback (string.Empty, 0, "Error").
With a deserializer DTO, missing fields silently get CLR defaults — null for string, not string.Empty.
Matching the same semantics would require nullable annotations and post-construction fixup.
Decoupled domain type.
ManifestDiagnostic is the public API type.
A deserializer approach would require either a separate private DTO (plus a mapping step) or
decorating ManifestDiagnostic itself with [JsonPropertyName] attributes, leaking the wire format into the
public model.
ManifestErrorId and ManifestDiagnosticLevel require custom handling regardless.
The JSON carries strings ("RequiredFieldMissing", "Warning"); the deserializer cannot map these automatically.
You would need a JsonConverter<ManifestErrorId> and a JsonConverter<ManifestDiagnosticLevel> —
roughly the same logic that is inlined today, just more indirectly.
Resilience to format changes.
TryGetProperty degrades gracefully field-by-field.
A deserializer that hits an unexpected property or type mismatch can throw (or silently drop) the whole object.
Because the JSON producer is native C++, subtle type differences (e.g., integer vs. string for line) are more
likely.
In favor of JsonSerializer.Deserialize<T>
Less boilerplate as the schema grows.
If the number of fields doubles, the deserializer approach scales better than one TryGetProperty call per field.
Correctness guarantees from the type system.
[JsonRequired] can enforce mandatory fields and produce a clear exception rather than a silently zero-filled
ManifestDiagnostic.
Easier isolated testing.
DTO deserialization can be tested independently of the rest of the parsing logic.
Verdict
The manual approach is the right call here.
The schema is stable and small (8 fields), both enum conversions need custom logic regardless,
ManifestDiagnostic is a public type that should not be decorated with JSON attributes,
and TryGetProperty-with-fallback gives controlled degradation across the C++/C# boundary.
A deserializer would require a private DTO, custom converters, and a mapping step —
more total code for no meaningful gain at this scale.
Change
Adds a new flag to request JSON from manifest creation/validation pass. Doing so enables the interop layer to provide the validation warnings/errors as an object model.
Microsoft Reviewers: Open in CodeFlow