Skip to content

Allow adding json type modifiers to object types - #52

Closed
myieye wants to merge 1 commit into
mainfrom
allow-adding-json-type-modifiers-to-objects
Closed

myieye wants to merge 1 commit into
mainfrom
allow-adding-json-type-modifiers-to-objects

Conversation

@myieye

@myieye myieye commented Sep 24, 2025 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Enable per-type customization of JSON metadata during adapter registration, allowing finer control over serialization.
  • Refactor
    • Introduced a cached registrations map used after configuration is frozen, ensuring consistent application of JSON modifiers and improving stability.
  • Style
    • Minor formatting cleanups with no functional impact.

@coderabbitai

coderabbitai Bot commented Sep 24, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Introduces an optional JsonTypeInfo modifier across adapter registration and JSON configuration. Adds a jsonTypeModifier parameter to CustomAdapterProvider.Add, extends AdapterRegistration to carry it, and updates CrdtConfig to invoke per-type modifiers via a cached RegistrationsByType map, which is frozen and reused after configuration.

Changes

Cohort / File(s) Summary
Adapter registration API
src/SIL.Harmony/Adapters/CustomAdapterProvider.cs
Add optional parameter Action<JsonTypeInfo>? jsonTypeModifier to Add<T> and pass it into AdapterRegistration creation. Minor formatting tweaks.
AdapterRegistration extension
src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs
Extend AdapterRegistration to include Action<JsonTypeInfo>? JsonTypeModifier = null; add using System.Text.Json.Serialization.Metadata. No interface changes.
CRDT config and caching
src/SIL.Harmony/CrdtConfig.cs
Introduce cached RegistrationsByType (backed by _frozenRegistrationsByType) in ObjectTypeListBuilder; update Freeze to populate cache. Update JSON type modifier logic to lookup matching registration and invoke its JsonTypeModifier when present.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Developer
  participant CAP as CustomAdapterProvider
  participant OR as AdapterRegistration
  participant OTB as ObjectTypeListBuilder
  participant CC as CrdtConfig
  participant STJ as System.Text.Json

  Dev->>CAP: Add<T>(configureEntry?, jsonTypeModifier?)
  CAP->>OR: Create AdapterRegistration(T, EntityBuilder, JsonTypeModifier)
  CAP-->>Dev: Registration stored via provider(s)

  Note over CC,OTB: During configuration freeze
  CC->>OTB: Freeze()
  OTB->>OTB: Compute RegistrationsByType (or use cached)
  OTB-->>CC: Cached map ready

  Note over STJ,CC: At runtime JSON metadata creation
  STJ->>CC: Apply global JsonTypeModifier(typeInfo)
  CC->>OTB: Find registration by type
  alt Registration found with JsonTypeModifier
    CC->>OR: Invoke registration.JsonTypeModifier(typeInfo)
  else No per-type modifier
    CC-->>STJ: No-op
  end
  STJ-->>Dev: Finalized JsonTypeInfo
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibbled the code with whiskered care,
A tiny tweak to types we share—
Per-type spells for JSON light,
Cached maps snug through freezing night.
Hop, hop! The adapters sing,
As metadata gets its spring. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately describes the primary change—allowing JSON type modifiers to be added to object types—which aligns with the added jsonTypeModifier parameters and registration changes in the diff. It is concise and specific, avoiding vague phrasing or unrelated details. A reviewer scanning PR history will understand the main intent from this title alone.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch allow-adding-json-type-modifiers-to-objects

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/SIL.Harmony/Adapters/CustomAdapterProvider.cs (1)

22-28: Expose jsonTypeModifier on AddWithCustomPolymorphicMapping as well

Right now, callers using AddWithCustomPolymorphicMapping can’t pass a JsonTypeInfo modifier without switching to Add. Consider adding an overload to keep the ergonomic flow consistent.

Example (new overload):

public CustomAdapterProvider<TCommonInterface, TCustomAdapter> AddWithCustomPolymorphicMapping<T>(
    string typeName,
    Action<EntityTypeBuilder<T>>? configureEntry = null,
    Action<JsonTypeInfo>? jsonTypeModifier = null
) where T : class, TCommonInterface
{
    JsonTypes.AddDerivedType(typeof(TCommonInterface), typeof(T), typeName);
    return Add(configureEntry, jsonTypeModifier);
}
src/SIL.Harmony/CrdtConfig.cs (2)

73-77: Prefer TryGetValue over GetValueOrDefault and remove redundant equality check

Avoid relying on extension availability and simplify the condition.

-        var registration = ObjectTypeListBuilder.RegistrationsByType.GetValueOrDefault(typeInfo.Type);
-        if (registration?.JsonTypeModifier is not null && registration.ObjectDbType == typeInfo.Type)
-        {
-            registration.JsonTypeModifier(typeInfo);
-        }
+        if (ObjectTypeListBuilder.RegistrationsByType.TryGetValue(typeInfo.Type, out var registration)
+            && registration.JsonTypeModifier is not null)
+        {
+            registration.JsonTypeModifier(typeInfo);
+        }

166-169: Duplicate registration guard (optional)

ToDictionary will throw a generic exception on duplicate ObjectDbType. Consider emitting a clearer error by pre‑validating duplicates.

Sketch:

private IReadOnlyDictionary<Type, AdapterRegistration> BuildRegistrationsByType()
{
    var regs = AdapterProviders.SelectMany(p => p.GetRegistrations());
    var dups = regs.GroupBy(r => r.ObjectDbType).Where(g => g.Skip(1).Any()).Select(g => g.Key).ToArray();
    if (dups.Length > 0)
        throw new InvalidOperationException($"Multiple adapter registrations for: {string.Join(", ", dups.Select(t => t.FullName))}");
    return regs.ToDictionary(r => r.ObjectDbType);
}

Then have RegistrationsByType delegate to BuildRegistrationsByType() when not frozen.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17334b3 and 8027780.

📒 Files selected for processing (3)
  • src/SIL.Harmony/Adapters/CustomAdapterProvider.cs (4 hunks)
  • src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs (1 hunks)
  • src/SIL.Harmony/CrdtConfig.cs (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs (1)
src/SIL.Harmony/CrdtConfig.cs (2)
  • Action (39-42)
  • JsonTypeModifier (52-78)
src/SIL.Harmony/Adapters/CustomAdapterProvider.cs (1)
src/SIL.Harmony/CrdtConfig.cs (1)
  • Action (39-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (4)
src/SIL.Harmony/Adapters/CustomAdapterProvider.cs (2)

30-33: Add JSON type modifier: API extension looks good

New optional parameter is well-placed and backward‑compatible.


37-44: Correctly forwarding jsonTypeModifier to AdapterRegistration

Forwarding the delegate into the registration ensures per‑type customization is reachable from the resolver.

src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs (1)

7-7: AdapterRegistration gains optional JsonTypeModifier

Change is internal, backward‑compatible (default = null), and aligns with usage.

src/SIL.Harmony/CrdtConfig.cs (1)

140-141: Freezing and caching registrations map

Capturing a frozen snapshot before wiring model configurations is a good move for stability.

@myieye

myieye commented Sep 26, 2025

Copy link
Copy Markdown
Contributor Author

Not actually necessary.
The JsonSerializationOptions in CrdtConfig are public and thus the TypeInfoResolver can be modified.

@myieye myieye closed this Sep 26, 2025
@myieye
myieye deleted the allow-adding-json-type-modifiers-to-objects branch September 26, 2025 09:59
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.

1 participant