Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/wild-dolls-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@biomejs/biome": patch
---

Added the nursery rule [`noEmptyObjectKeys`](https://biomejs.dev/linter/rules/no-empty-object-keys/), which disallows the use of empty keys in JSON objects.

**Invalid:**

```json
{
"": "value"
}
```
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/biome_configuration/src/analyzer/linter/rules.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/biome_diagnostics_categories/src/categories.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/biome_json_analyze/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ name = "json_analyzer"
biome_analyze = { workspace = true }
biome_analyze_macros = { workspace = true }
biome_console = { workspace = true }
biome_deserialize = { workspace = true }
biome_diagnostics = { workspace = true }
biome_json_factory = { workspace = true }
biome_json_syntax = { workspace = true }
Expand Down
101 changes: 101 additions & 0 deletions crates/biome_json_analyze/src/lint/nursery/no_empty_object_keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use biome_analyze::{
Ast, Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule,
};
use biome_console::markup;
use biome_deserialize::json::unescape_json_string;
use biome_json_syntax::JsonMemberName;
use biome_rowan::AstNode;
use biome_rule_options::no_empty_object_keys::NoEmptyObjectKeysOptions;

declare_lint_rule! {
/// Disallow empty keys in JSON objects.
///
/// In JSON, using empty keys (keys that are empty strings or contain only whitespace) can lead to accessibility and maintenance issues.
/// While technically valid in JSON, empty keys make objects harder to read, can cause confusion when debugging, and may create problems with some JSON parsers or processors.
/// Additionally, empty keys often indicate mistakes or oversights in the processes.
///
/// ## Examples
///
/// ### Invalid
///
/// ```json,expect_diagnostic
/// {
/// "": "value"
/// }
/// ```
///
/// ```json,expect_diagnostic
/// {
/// "validKey": "value",
/// "": "another value"
/// }
/// ```
///
/// ```json,expect_diagnostic
/// {
/// " ": "space as key"
/// }
/// ```
///
/// ```json,expect_diagnostic
/// {
/// "\t": "tab as key"
/// }
/// ```
///
/// ```json,expect_diagnostic
/// {
/// "\n": "newline as key"
/// }
/// ```
///
/// ### Valid
///
/// ```json
/// {
/// "key": "value"
/// }
/// ```
///
pub NoEmptyObjectKeys {
version: "next",
name: "noEmptyObjectKeys",
language: "json",
recommended: false,
sources: &[RuleSource::EslintJson("no-empty-keys").same()],
}
}

impl Rule for NoEmptyObjectKeys {
type Query = Ast<JsonMemberName>;
type State = ();
type Signals = Option<Self::State>;
type Options = NoEmptyObjectKeysOptions;

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let node = ctx.query();
let value = node.inner_string_text().ok()?;
let binding = unescape_json_string(value);
if binding.trim().is_empty() {
return Some(());
}

None
}

fn diagnostic(ctx: &RuleContext<Self>, _state: &Self::State) -> Option<RuleDiagnostic> {
let span = ctx.query().range();
Some(
RuleDiagnostic::new(
rule_category!(),
span,
markup! {
"Unexpected empty object key."
},
)
.note(markup! {
"Empty keys often cause confusion and may cause issues with parsers or processors. Either remove this property or provide a meaningful key name."
}),
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"": "another value",
" ": "space as key",
"\t": "tab as key",
"\n": "newline as key",
"\n\n\n": "multi newline as key"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
source: crates/biome_json_analyze/tests/spec_tests.rs
expression: invalid.json
---
# Input
```json
{
"": "another value",
" ": "space as key",
"\t": "tab as key",
"\n": "newline as key",
"\n\n\n": "multi newline as key"
}

```

# Diagnostics
```
invalid.json:2:3 lint/nursery/noEmptyObjectKeys ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

i Unexpected empty object key.

1 │ {
> 2 │ "": "another value",
│ ^^
3 │ " ": "space as key",
4 │ "\t": "tab as key",

i Empty keys often cause confusion and may cause issues with parsers or processors. Either remove this property or provide a meaningful key name.

i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.


```

```
invalid.json:3:3 lint/nursery/noEmptyObjectKeys ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

i Unexpected empty object key.

1 │ {
2 │ "": "another value",
> 3 │ " ": "space as key",
│ ^^^
4 │ "\t": "tab as key",
5 │ "\n": "newline as key",

i Empty keys often cause confusion and may cause issues with parsers or processors. Either remove this property or provide a meaningful key name.

i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.


```

```
invalid.json:4:3 lint/nursery/noEmptyObjectKeys ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

i Unexpected empty object key.

2 │ "": "another value",
3 │ " ": "space as key",
> 4 │ "\t": "tab as key",
│ ^^^^
5 │ "\n": "newline as key",
6 │ "\n\n\n": "multi newline as key"

i Empty keys often cause confusion and may cause issues with parsers or processors. Either remove this property or provide a meaningful key name.

i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.


```

```
invalid.json:5:3 lint/nursery/noEmptyObjectKeys ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

i Unexpected empty object key.

3 │ " ": "space as key",
4 │ "\t": "tab as key",
> 5 │ "\n": "newline as key",
│ ^^^^
6 │ "\n\n\n": "multi newline as key"
7 │ }

i Empty keys often cause confusion and may cause issues with parsers or processors. Either remove this property or provide a meaningful key name.

i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.


```

```
invalid.json:6:3 lint/nursery/noEmptyObjectKeys ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

i Unexpected empty object key.

4 │ "\t": "tab as key",
5 │ "\n": "newline as key",
> 6 │ "\n\n\n": "multi newline as key"
│ ^^^^^^^^
7 │ }
8 │

i Empty keys often cause confusion and may cause issues with parsers or processors. Either remove this property or provide a meaningful key name.

i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.


```
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"key1": "value1",
"key2": {
"nestedKey": "nested value",
" nestedKey \n\t ": "nested value"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
source: crates/biome_json_analyze/tests/spec_tests.rs
expression: valid.json
---
# Input
```json
{
"key1": "value1",
"key2": {
"nestedKey": "nested value",
" nestedKey \n\t ": "nested value"
}
}

```
1 change: 1 addition & 0 deletions crates/biome_rule_options/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub mod no_empty_block;
pub mod no_empty_block_statements;
pub mod no_empty_character_class_in_regex;
pub mod no_empty_interface;
pub mod no_empty_object_keys;
pub mod no_empty_pattern;
pub mod no_empty_source;
pub mod no_empty_type_parameters;
Expand Down
6 changes: 6 additions & 0 deletions crates/biome_rule_options/src/no_empty_object_keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use biome_deserialize_macros::{Deserializable, Merge};
use serde::{Deserialize, Serialize};
#[derive(Default, Clone, Debug, Deserialize, Deserializable, Merge, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields, default)]
pub struct NoEmptyObjectKeysOptions {}
14 changes: 14 additions & 0 deletions packages/@biomejs/backend-jsonrpc/src/workspace.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading