Skip to content

feat: Map JSON DataContent to Part.Data - #448

Open
SergeyMenshykh wants to merge 4 commits into
a2aproject:mainfrom
SergeyMenshykh:fix/json-data-content-part
Open

feat: Map JSON DataContent to Part.Data#448
SergeyMenshykh wants to merge 4 commits into
a2aproject:mainfrom
SergeyMenshykh:fix/json-data-content-part

Conversation

@SergeyMenshykh

Copy link
Copy Markdown
Collaborator

Summary

  • map JSON DataContent payloads to structured Part.Data values
  • recognize application/json, media type parameters, and +json suffixes
  • preserve the original media type and surface invalid JSON
  • keep non-JSON DataContent mapped to Part.Raw

Tests

  • dotnet test tests\A2A.UnitTests\A2A.UnitTests.csproj --no-restore --filter "FullyQualifiedName~AIContentExtensionsTests" --verbosity quiet

Fixes #447

Map JSON DataContent payloads to structured Part.Data values while
preserving their media type. Continue using Part.Raw for non-JSON data
and surface malformed content declared as JSON.

Fixes a2aproject#447

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ea72bc53-dec7-452c-94f6-6a0a50e56b66
@SergeyMenshykh SergeyMenshykh changed the title Map JSON DataContent to Part.Data feat: Map JSON DataContent to Part.Data Aug 6, 2026
@chopmob-cloud

Copy link
Copy Markdown
Contributor

Verified this independently against current main (built net8.0 and net10.0, ran the round trip). The forward direction here is correct: JSON DataContent maps to Part.Data, the +json structured suffix and media type parameters are recognised, the original media type is preserved onto the part, and invalid JSON declared as JSON now surfaces a JsonException. All of that matches what #447 asked for, and the added tests cover it.

One observation on the "symmetric round-tripping" motivation from #447. The symmetry currently holds only for exactly application/json. The reverse leg, ToAIContent's part.Data branch, is unchanged and hardcodes "application/json", ignoring part.MediaType. So the media type this PR carefully preserves on the way out is dropped on the way back:

in=application/json                | forwardPart=application/json                | reverse=application/json
in=application/problem+json        | forwardPart=application/problem+json        | reverse=application/json
in=application/vnd.acme.thing+json | forwardPart=application/vnd.acme.thing+json | reverse=application/json

Media type parameters and casing are lost the same way (application/json; charset=utf-8 comes back as bare application/json).

A small change on the reverse branch closes the loop for the +json types the forward direction now supports:

content = new DataContent(
    JsonSerializer.SerializeToUtf8Bytes(data, A2AJsonUtilities.DefaultOptions.GetTypeInfo(typeof(JsonElement))),
    IsJsonMediaType(part.MediaType) ? part.MediaType! : "application/json");

Guarding on IsJsonMediaType (rather than a bare part.MediaType ?? "application/json") keeps the invariant that JSON bytes are never labelled with a non-JSON media type. With this, application/problem+json and application/vnd.acme.thing+json round trip losslessly, and all existing AIContentExtensionsTests stay green on both target frameworks. Happy to open a follow up if that is useful, or it folds naturally into this PR.

darrelmiller and others added 3 commits August 17, 2026 22:58
Preserve valid JSON media types when converting structured Part.Data
values back to DataContent, while falling back to application/json for
missing or non-JSON media types.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ea72bc53-dec7-452c-94f6-6a0a50e56b66
@SergeyMenshykh

Copy link
Copy Markdown
Collaborator Author

Verified this independently against current main (built net8.0 and net10.0, ran the round trip). The forward direction here is correct: JSON DataContent maps to Part.Data, the +json structured suffix and media type parameters are recognised, the original media type is preserved onto the part, and invalid JSON declared as JSON now surfaces a JsonException. All of that matches what #447 asked for, and the added tests cover it.

One observation on the "symmetric round-tripping" motivation from #447. The symmetry currently holds only for exactly application/json. The reverse leg, ToAIContent's part.Data branch, is unchanged and hardcodes "application/json", ignoring part.MediaType. So the media type this PR carefully preserves on the way out is dropped on the way back:

in=application/json                | forwardPart=application/json                | reverse=application/json
in=application/problem+json        | forwardPart=application/problem+json        | reverse=application/json
in=application/vnd.acme.thing+json | forwardPart=application/vnd.acme.thing+json | reverse=application/json

Media type parameters and casing are lost the same way (application/json; charset=utf-8 comes back as bare application/json).

A small change on the reverse branch closes the loop for the +json types the forward direction now supports:

content = new DataContent(
    JsonSerializer.SerializeToUtf8Bytes(data, A2AJsonUtilities.DefaultOptions.GetTypeInfo(typeof(JsonElement))),
    IsJsonMediaType(part.MediaType) ? part.MediaType! : "application/json");

Guarding on IsJsonMediaType (rather than a bare part.MediaType ?? "application/json") keeps the invariant that JSON bytes are never labelled with a non-JSON media type. With this, application/problem+json and application/vnd.acme.thing+json round trip losslessly, and all existing AIContentExtensionsTests stay green on both target frameworks. Happy to open a follow up if that is useful, or it folds naturally into this PR.

Thanks for catching this. It makes sense, and I’ve added the suggested change and tests.

@SergeyMenshykh SergeyMenshykh self-assigned this Aug 18, 2026
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.

Map JSON DataContent to Part.Data instead of Part.Raw

3 participants