Skip to content

Use json source generator#1656

Open
bart-vmware wants to merge 14 commits intomainfrom
use-json-source-generator
Open

Use json source generator#1656
bart-vmware wants to merge 14 commits intomainfrom
use-json-source-generator

Conversation

@bart-vmware
Copy link
Member

@bart-vmware bart-vmware commented Mar 6, 2026

Description

This PR migrates System.Text.Json serialization from reflection-based to compile-time source-generated JsonSerializerContext classes across the non-actuator parts of the codebase (actuator endpoints are excluded because their serializer options are configurable at runtime).

Key changes:

  1. Source-generated JSON serialization -- Six new JsonSerializerContext subclasses replace static JsonSerializerOptions instances and update (de)serialization calls throughout Eureka, HttpClients, Cloud Foundry middleware, Management port middleware, and SpringBootAdmin client.

  2. Explicit [JsonPropertyName] on all serialized properties that are exposed at actuator endpoints -- Guards against wire-level breaking changes when users configure an alternate casing policy, since the property names are dictated by Spring.

  3. Cloud Foundry permissions reworked -- Switched from v2 to v3 cloud controller API, replaced loose Dictionary<string, JsonElement> parsing with a strongly-typed PermissionsResponse, and improved error handling in parsing Cloud Controller responses (graceful failure instead of throwing SecurityException). Test mock scenarios were renamed for clarity ("success" -> "full-permissions", "no_sensitive_data" -> "restricted-permissions") and new scenarios added for "no-permissions" and "broken-response".

  4. Loggers actuator bug fixes -- Now respects configured serializer options when reading request bodies, corrects nullability, and no longer assumes RESET when the request body can't be parsed.

  5. Test improvements -- Expanded serialization roundtrip tests for Eureka types, added ToString() debug output coverage, updated CloudFoundry mock URLs and scenarios to match the new permission logic.

Closes #970.

Quality checklist

  • Your code complies with our Coding Style.
  • You've updated unit and/or integration tests for your change, where applicable.
  • You've updated documentation for your change, where applicable.
    If your change affects other repositories, such as Documentation, Samples and/or MainSite, add linked PRs here.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.
  • You've added required license files and/or file headers (explaining where the code came from with proper attribution), where code is copied from StackOverflow, a blog, or OSS.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 6, 2026

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

Summary - All Code Coverage (ubuntu-latest)

Line coverage Branch coverage

Assembly Line coverage Branch coverage
Steeltoe.Bootstrap.AutoConfiguration 97.4% 100%
Steeltoe.Common 84.3% 77.8%
Steeltoe.Common.Certificates 96.2% 85.5%
Steeltoe.Common.Hosting 84% 70%
Steeltoe.Common.Http 100% 85.2%
Steeltoe.Common.Logging 81.1% 56.2%
Steeltoe.Common.Net 64.5% 66.6%
Steeltoe.Configuration.Abstractions 98.6% 91.4%
Steeltoe.Configuration.CloudFoundry 99.1% 91.8%
Steeltoe.Configuration.ConfigServer 97.2% 91.6%
Steeltoe.Configuration.Encryption 97.6% 92.4%
Steeltoe.Configuration.Kubernetes.ServiceBindings 95.1% 89.3%
Steeltoe.Configuration.Placeholder 93.8% 84.7%
Steeltoe.Configuration.RandomValue 93.2% 90%
Steeltoe.Configuration.SpringBoot 98.3% 95%
Steeltoe.Connectors 93.9% 89.4%
Steeltoe.Connectors.EntityFrameworkCore 81.5% 75%
Steeltoe.Discovery.Configuration 92.3% 100%
Steeltoe.Discovery.Consul 97.6% 96.5%
Steeltoe.Discovery.Eureka 92.2% 85.3%
Steeltoe.Discovery.HttpClients 94.3% 95.4%
Steeltoe.Logging.Abstractions 99.4% 96.9%
Steeltoe.Logging.DynamicConsole 100% 95.4%
Steeltoe.Logging.DynamicSerilog 99.1% 95.4%
Steeltoe.Management.Abstractions 100% 100%
Steeltoe.Management.Endpoint 95.8% 89%
Steeltoe.Management.Prometheus 95.8% 91.6%
Steeltoe.Management.Tasks 100% ****
Steeltoe.Management.Tracing 100% 75%
Steeltoe.Security.Authentication.JwtBearer 100% 100%
Steeltoe.Security.Authentication.OpenIdConnect 73.8% 59%
Steeltoe.Security.Authorization.Certificate 96.7% 75%
Steeltoe.Security.DataProtection.Redis 100% ****

@bart-vmware bart-vmware marked this pull request as ready for review March 6, 2026 10:18
@bart-vmware bart-vmware requested a review from TimHess March 6, 2026 10:18
TimHess
TimHess previously approved these changes Mar 6, 2026
Copy link
Member

@TimHess TimHess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM, some nice improvements! Comments can be resolved if you don't think changes are needed for any of them


[JsonSourceGenerationOptions]
[JsonSerializable(typeof(Application))]
[JsonSerializable(typeof(SpringBootAdminApiClient.RegistrationResult))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not a big deal, but the PR description says it adds [JsonPropertyName] to all serialized properties to guard against wire-level breaking changes. But RegistrationResult.Id doesn't have one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, Cursor initially generated a very detailed description for the PR, so I asked to simplify it. I'll update the description to indicate that this matters to users who pass their own casing convention via configuration, which is only possible for actuator endpoints.

public Uri Uri { get; set; } = null!;
public Uri? NonSecureUri { get; set; }
public Uri? SecureUri { get; set; }
public IReadOnlyDictionary<string, string?> Metadata { get; set; } = null!;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these properties have [JsonPropertyName] set?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, this only matters for data exposed at actuator endpoints. Serializer options are not configurable here.

[Theory]
[InlineData(false, false, EndpointPermissions.None)]
[InlineData(false, true, EndpointPermissions.Restricted)]
[InlineData(true, false, EndpointPermissions.None)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you able to find out if this scenario is possible? It does seem implausible, so probably doesn't need extensive research

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked into it, just trying to be defensive by default.

LogChangeRequest(loggerName, level ?? "RESET");

if (!string.IsNullOrEmpty(loggerName))
if (changes.TryGetValue("configuredLevel", out string? level))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a good and safe change, but just wanted to confirm you validated that both SBA and Apps Manager send the expected request body and there aren't real cases of an actuator client sending an empty body here?

catch (Exception exception) when (!exception.IsCancellation())
{
throw new SecurityException($"Exception extracting permissions from json: {SecurityUtilities.SanitizeInput(json)}", exception);
return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's an exception during deserialization, it will be swallowed and the result will be Bad Gateway... While the scenario is pretty unlikely, and it will be pretty clear what happened, this could leave anybody trying to diagnose the situation with a more work to do trying to understand why it happened since they won't be able to see what that response body was

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they need to turn on debug logging. This is a scenario that should never happen, unless the Cloud Controller API changes or misbehaves. An API change requires a major version bump, while a misbehaving CC is a bug that Broadcom needs to investigate. I wouldn't expect end-users to go that deep.

@TimHess TimHess self-requested a review March 6, 2026 17:38
@TimHess TimHess dismissed their stale review March 6, 2026 17:39

v3 permissions api does not work

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.

Use System.Text.Json source generator

2 participants