fix: Use custom JsonConverter for A2AEvent and A2AResponse instead of [JsonPolymorphic] to fix discriminator deserialization issues#158
Conversation
8165caa to
e2e3e06
Compare
e2e3e06 to
5190265
Compare
5190265 to
77bf0ed
Compare
77bf0ed to
efc8a0f
Compare
efc8a0f to
4b3fe25
Compare
There was a problem hiding this comment.
Pull Request Overview
This PR replaces the [JsonPolymorphic] attribute with custom JsonConverter implementations for A2AEvent and A2AResponse to fix discriminator-based deserialization issues in AOT scenarios.
Key changes:
- Custom converters with explicit
kinddiscriminator routing for consistent serialization/deserialization - Added explicit
Kindproperty overrides to all concrete event types - Enhanced source-generated JSON context coverage for affected types
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/A2A/Models/A2AResponse.cs | Replaced [JsonPolymorphic] with custom converters and added abstract Kind property |
| src/A2A/Models/Message.cs | Added explicit Kind property override returning "message" |
| src/A2A/Models/AgentTask.cs | Added explicit Kind property override returning "task" |
| src/A2A/Models/TaskStatusUpdateEvent.cs | Added explicit Kind property override returning "status-update" |
| src/A2A/Models/TaskArtifactUpdateEvent.cs | Added explicit Kind property override returning "artifact-update" |
| src/A2A/A2AJsonUtilities.cs | Added missing type registrations for source-generated JSON context |
| tests/A2A.UnitTests/Models/A2AResponseTests.cs | Added comprehensive test coverage for new converter behavior |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| { | ||
| return a2aResponse; | ||
| } | ||
| throw new JsonException("JSON did not represent an A2AResponse instance."); |
There was a problem hiding this comment.
The Read method is being called on a ref Utf8JsonReader that has already been consumed by the previous call. This will cause the reader to be positioned incorrectly. You need to reset the reader position or pass a copy of the reader state.
| throw new JsonException("JSON did not represent an A2AResponse instance."); | |
| if (reader.TokenType != JsonTokenType.StartObject) | |
| { | |
| throw new JsonException("Expected StartObject token"); | |
| } | |
| using var document = JsonDocument.ParseValue(ref reader); | |
| var a2aResponse = document.RootElement.Deserialize(A2AJsonUtilities.JsonContext.Default.A2AResponse); | |
| if (a2aResponse is null) | |
| { | |
| throw new JsonException("JSON did not represent an A2AResponse instance."); | |
| } | |
| return a2aResponse; |
There was a problem hiding this comment.
Correct me if I am wrong but this comment seems false-positive to me.
4b3fe25 to
17ac04c
Compare
…ead of `[JsonPolymorphic]` to fix discriminator deserialization issues
17ac04c to
1dbc533
Compare
|
Closing in favor of #163 |
Summary
[JsonPolymorphic]with customJsonConverterimplementations forA2AEventandA2AResponseto fix discriminator-based deserialization.JsonContextand explicitkinddiscriminators.Problem
[JsonPolymorphic]produced inconsistent discriminator deserialization across contexts/AOT, causing events to fail to materialize to concrete types or lose thekindfield.Changes
A2AEventConverterandA2AResponseConverterwith strictkindhandling:kind→message,task,status-update,artifact-update; throw on unknown/missing.A2AJsonUtilities.JsonContextto concrete metadata.Kindoverrides:Message→message,AgentTask→task,TaskStatusUpdateEvent→status-update,TaskArtifactUpdateEvent→artifact-update.A2AJsonUtilities.JsonContextfor affected types.tests/A2A.UnitTests/Models/A2AResponseTests.cs.Testing
A2AEvent: succeeds for all four kinds; throws for unknown/missingkind.A2AResponse: succeeds formessage/task; throws forstatus-update/artifact-update.A2AEvent/A2AResponse:kindis always present and correct; selected exact-shape assertions for known cases.dotnet test A2A.slnx -v mpasses on net8.0/net9.0.Impact
A2AEvent/TaskUpdateEvent: they must implementKind, and customkindvalues are not yet routed by the new converters.Migration Notes
public override string Kind => "<your-kind>";and handle custom routing via an app-level converter or open an issue to extend built-in routing.Files
src/A2A/Models/A2AResponse.cs,src/A2A/Models/Message.cs,src/A2A/Models/AgentTask.cs,src/A2A/Models/TaskStatusUpdateEvent.cs,src/A2A/Models/TaskArtifactUpdateEvent.cs,src/A2A/A2AJsonUtilities.cstests/A2A.UnitTests/Models/A2AResponseTests.csRelated