Skip to content

feat: json5 source support#124

Closed
tenuous-guidance wants to merge 2 commits intox52dev:mainfrom
tenuous-guidance:json5
Closed

feat: json5 source support#124
tenuous-guidance wants to merge 2 commits intox52dev:mainfrom
tenuous-guidance:json5

Conversation

@tenuous-guidance
Copy link
Copy Markdown
Contributor

@tenuous-guidance tenuous-guidance commented Sep 2, 2024

Fixes #122

My biggest concern here is that it's easy to typo, but I'm not sure what a better naming might be? Maybe JsonFive but that would likely break user expectations.

Summary by CodeRabbit

  • New Features

    • Added JSON5 as a new configuration source format, allowing configurations to leverage JSON5 syntax including comments and extended features for improved readability.
  • Documentation

    • Updated changelog documenting the new JSON5 source support.

@tenuous-guidance
Copy link
Copy Markdown
Contributor Author

tenuous-guidance commented Sep 2, 2024

$ cargo update -p=toml_edit --precise=0.21.0
error: There are multiple `toml_edit` packages in your project, and the specification `toml_edit` is ambiguous.
Please re-run this command with one of the following specifications:
  toml_edit@0.21.1
  toml_edit@0.22.20

$ cargo tree -i toml_edit
toml_edit v0.21.1
└── toml v0.8.8
    ├── confik v0.11.7
    │   [dev-dependencies]
    │   └── confik-macros v0.11.1 (proc-macro)
    │       └── confik v0.11.7 (*)
    └── trybuild v1.0.99
        [dev-dependencies]
        └── confik-macros v0.11.1 (proc-macro) (*)
    [dev-dependencies]
    └── confik-macros v0.11.1 (proc-macro) (*)

$ cargo tree -i toml_edit@0.22.20
error: package ID specification `toml_edit@0.22.20` did not match any packages
Did you mean one of these?

  toml_edit@0.21.1

$ cargo update -p=toml_edit@0.22.20 --precise=0.21.0
    Updating crates.io index
error: failed to select a version for the requirement `toml_edit = "^0.22.20"`
candidate versions found which didn't match: 0.21.0
location searched: crates.io index
required by package `proc-macro-crate v3.2.0`
    ... which satisfies dependency `proc-macro-crate = "^3"` (locked to 3.2.0) of package `borsh-derive v1.5.1`
    ... which satisfies dependency `borsh-derive = "~1.5.1"` (locked to 1.5.1) of package `borsh v1.5.1`
    ... which satisfies dependency `borsh = "^1.1.1"` (locked to 1.5.1) of package `rust_decimal v1.36.0`
    ... which satisfies dependency `rust_decimal = "^1"` (locked to 1.36.0) of package `confik v0.11.7 (/home/user/git_repo/3pp/confik/confik)`
    ... which satisfies dependency `confik = "^0.11"` (locked to 0.11.7) of package `confik-macros v0.11.1 (/home/user/git_repo/3pp/confik/confik-macros)`

I think we're hitting a bug in cargo update. Running cargo update -p=toml_edit@0.21.1 --precise=0.21.0 will work, but only until we change toml_edit version.

How would you like to proceed @robjtede?

@robjtede
Copy link
Copy Markdown
Member

robjtede commented Mar 7, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 7, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

This pull request introduces JSON5 support as an optional feature to the confik configuration library. It adds a new Json5Source struct that implements the Source trait, enabling users to parse JSON5 format configurations. The feature is gated behind a json5 Cargo feature flag and properly integrated into the public API.

Changes

Cohort / File(s) Summary
Feature Declaration & Dependencies
confik/Cargo.toml
Added json5 optional feature and json5 = { version = "0.4", optional = true } dependency.
JSON5 Source Implementation
confik/src/sources/json5_source.rs
New file implementing Json5Source<'a> struct with Source trait, supporting JSON5 parsing with configurable secret handling. Includes unit tests for defaults, cloning, and end-to-end configuration building.
Module Integration & Public API
confik/src/sources/mod.rs, confik/src/lib.rs
Added json5_source module declaration and conditional public re-export of Json5Source under #[cfg(feature = "json5")].
Documentation
confik/CHANGELOG.md
Added changelog entry documenting JSON5 source support addition.

Sequence Diagram

sequenceDiagram
    participant App as Application
    participant J5S as Json5Source
    participant J5 as json5 Parser
    participant Config as ConfigurationBuilder

    App->>J5S: new(json5_contents)
    activate J5S
    J5S->>J5S: store contents & allow_secrets flag
    deactivate J5S
    
    App->>J5S: provide::<Config>()
    activate J5S
    J5S->>J5: from_str(contents)
    activate J5
    J5-->>J5S: parsed JSON5 data
    deactivate J5
    J5S->>Config: deserialize parsed data
    activate Config
    Config-->>J5S: Config<T>
    deactivate Config
    J5S-->>App: Result<T, Error>
    deactivate J5S
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A JSON5 source hops into the fray,
Comments and trailing commas at play,
Secrets gated, configs configured with grace,
New features adding speed to this space! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: json5 source support' directly and clearly summarizes the main change—adding JSON5 source support to the confik configuration system.
Linked Issues check ✅ Passed The pull request successfully implements JSON5 support as required by issue #122. It adds Json5Source struct, trait implementations, feature gating, and includes tests for proper JSON5 parsing and field mapping.
Out of Scope Changes check ✅ Passed All changes directly relate to implementing JSON5 source support. No unrelated modifications to other features, functionality, or dependencies outside the scope of issue #122 were identified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@confik/src/sources/json5_source.rs`:
- Around line 5-14: The public doc comments for the Json5Source type and its
constructor incorrectly say "JSON" — update them to say "JSON5" (e.g., change "A
[`Source`] containing raw JSON data." and "Creates a [`Source`] containing raw
JSON data." to mention "raw JSON5 data" and optionally note that this accepts
JSON5 syntax/extensions). Edit the doc comments on the Json5Source struct and
impl/new function to reference JSON5 and JSON5-specific parsing behavior so
docs.rs and IDE hovers show the correct format.
- Around line 28-35: The impl currently omits the trait generic and introduces a
local T in provide; change the impl to implement the generic trait by declaring
impl<'a, T: ConfigurationBuilder> Source<T> for Json5Source<'a>, keep
allows_secrets(&self) as-is, and update provide to match the trait signature fn
provide(&self) -> Result<T, Box<dyn Error + Sync + Send>> and return
Ok(json5::from_str::<T>(&self.contents)?); this ensures Json5Source implements
Source<T> for the appropriate T.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 60dc5ca7-4533-4583-a97a-20b51eb192cb

📥 Commits

Reviewing files that changed from the base of the PR and between 1f05084 and 392dfb0.

📒 Files selected for processing (5)
  • confik/CHANGELOG.md
  • confik/Cargo.toml
  • confik/src/lib.rs
  • confik/src/sources/json5_source.rs
  • confik/src/sources/mod.rs

Comment on lines +5 to +14
/// A [`Source`] containing raw JSON data.
#[derive(Clone)]
pub struct Json5Source<'a> {
contents: Cow<'a, str>,
allow_secrets: bool,
}

impl<'a> Json5Source<'a> {
/// Creates a [`Source`] containing raw JSON data.
pub fn new(contents: impl Into<Cow<'a, str>>) -> Self {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update the public docs to say JSON5, not JSON.

Both doc comments still describe strict JSON, but this type accepts JSON5 syntax. That will show up incorrectly in docs.rs and IDE hovers.

💡 Suggested change
-/// A [`Source`] containing raw JSON data.
+/// A [`Source`] containing raw JSON5 data.
@@
-    /// Creates a [`Source`] containing raw JSON data.
+    /// Creates a [`Source`] containing raw JSON5 data.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// A [`Source`] containing raw JSON data.
#[derive(Clone)]
pub struct Json5Source<'a> {
contents: Cow<'a, str>,
allow_secrets: bool,
}
impl<'a> Json5Source<'a> {
/// Creates a [`Source`] containing raw JSON data.
pub fn new(contents: impl Into<Cow<'a, str>>) -> Self {
/// A [`Source`] containing raw JSON5 data.
#[derive(Clone)]
pub struct Json5Source<'a> {
contents: Cow<'a, str>,
allow_secrets: bool,
}
impl<'a> Json5Source<'a> {
/// Creates a [`Source`] containing raw JSON5 data.
pub fn new(contents: impl Into<Cow<'a, str>>) -> Self {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@confik/src/sources/json5_source.rs` around lines 5 - 14, The public doc
comments for the Json5Source type and its constructor incorrectly say "JSON" —
update them to say "JSON5" (e.g., change "A [`Source`] containing raw JSON
data." and "Creates a [`Source`] containing raw JSON data." to mention "raw
JSON5 data" and optionally note that this accepts JSON5 syntax/extensions). Edit
the doc comments on the Json5Source struct and impl/new function to reference
JSON5 and JSON5-specific parsing behavior so docs.rs and IDE hovers show the
correct format.

Comment on lines +28 to +35
impl<'a> Source for Json5Source<'a> {
fn allows_secrets(&self) -> bool {
self.allow_secrets
}

fn provide<T: ConfigurationBuilder>(&self) -> Result<T, Box<dyn Error + Sync + Send>> {
Ok(json5::from_str(&self.contents)?)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Compare the generic `Source<T>` trait with the new JSON5 impl and existing source impls.

printf 'Trait definition:\n'
sed -n '1,20p' confik/src/sources/mod.rs

printf '\nNew JSON5 source impl:\n'
sed -n '28,40p' confik/src/sources/json5_source.rs

printf '\nExisting source impl patterns:\n'
fd '_source\.rs$' confik/src/sources -x sh -c '
  echo "--- $1"
  rg -n -C2 "impl.*Source|fn provide" "$1" || true
' sh {}

Repository: x52dev/confik

Length of output: 5049


🏁 Script executed:

# Find the test file for json5_source and examine the assertions
fd 'json5' confik/src -type f | grep -E '(test|spec)' || echo "Checking main file for tests..."

# Look at lines 54, 60, 61 in json5_source.rs to see if there are assertions there
wc -l confik/src/sources/json5_source.rs

# Get the full content to see the assertions
cat -n confik/src/sources/json5_source.rs | grep -A5 -B5 -E '(54|60|61):'

Repository: x52dev/confik

Length of output: 314


🏁 Script executed:

sed -n '50,65p' confik/src/sources/json5_source.rs

Repository: x52dev/confik

Length of output: 399


Implement Source<T> here; the current impl does not match the trait.

Line 28 omits the trait generic, and Line 33 changes the trait method signature by introducing its own T. That impl cannot satisfy Source<T>, which is why the current checks fail.

🐛 Suggested fix
-impl<'a> Source for Json5Source<'a> {
+impl<'a, T> Source<T> for Json5Source<'a>
+where
+    T: ConfigurationBuilder,
+{
     fn allows_secrets(&self) -> bool {
         self.allow_secrets
     }

-    fn provide<T: ConfigurationBuilder>(&self) -> Result<T, Box<dyn Error + Sync + Send>> {
+    fn provide(&self) -> Result<T, Box<dyn Error + Sync + Send>> {
         Ok(json5::from_str(&self.contents)?)
     }
 }
🧰 Tools
🪛 GitHub Check: clippy

[failure] 28-28:
missing generics for trait sources::Source

🪛 GitHub Check: docs

[failure] 28-28:
missing generics for trait sources::Source

🪛 GitHub Check: Test / stable

[failure] 28-28:
missing generics for trait sources::Source

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@confik/src/sources/json5_source.rs` around lines 28 - 35, The impl currently
omits the trait generic and introduces a local T in provide; change the impl to
implement the generic trait by declaring impl<'a, T: ConfigurationBuilder>
Source<T> for Json5Source<'a>, keep allows_secrets(&self) as-is, and update
provide to match the trait signature fn provide(&self) -> Result<T, Box<dyn
Error + Sync + Send>> and return Ok(json5::from_str::<T>(&self.contents)?); this
ensures Json5Source implements Source<T> for the appropriate T.

@robjtede robjtede closed this Mar 25, 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.

JSON5 support

2 participants