Skip to content

Add JsonReadMode and JsonWriteMode settings for configurable JSON handling#182

Merged
alex-clickhouse merged 7 commits intomainfrom
json-read-write-modes
Jan 26, 2026
Merged

Add JsonReadMode and JsonWriteMode settings for configurable JSON handling#182
alex-clickhouse merged 7 commits intomainfrom
json-read-write-modes

Conversation

@alex-clickhouse
Copy link
Copy Markdown
Collaborator

@alex-clickhouse alex-clickhouse commented Jan 22, 2026

Adds config options for JSON read and write handling.

The settings control input_format_binary_read_json_as_string and output_format_binary_write_json_as_string, with corresponding handling differences on the client side.

Writing behavior:

Input Type JsonWriteMode.String (default) JsonWriteMode.Binary
string Passed through directly Throws ArgumentException
JsonObject Serialized via ToJsonString() Throws ArgumentException
JsonNode Serialized via ToJsonString() Throws ArgumentException
Registered POCO Serialized via JsonSerializer.Serialize() Binary encoding with type hints, custom path attributes supported
Unregistered POCO Serialized via JsonSerializer.Serialize() Throws ClickHouseJsonSerializationException

Reading behavior:

String: sets output_format_binary_write_json_as_string=1 and just returns the string as it's sent by the server.
Binary (default): returns JsonNode. For the future at some point we'll add POCO deserialization as well.

The defaults (write string, read binary) are set to minimize impact on people upgrading from the previous version.

Also added a .None mode, for cases when users do not want any parameters added to the query (eg readonly, see the changes to that example).

Closes #93


Note

Introduces configurable JSON handling and propagates it through the driver.

  • Adds JsonReadMode/JsonWriteMode enums with defaults (Read: Binary -> JsonObject, Write: String -> serialize/forward strings); None mode avoids setting server params
  • Wires modes into ClickHouseConnectionStringBuilder, ClickHouseClientSettings, ClickHouseConnection/ClickHouseUriBuilder, TypeSettings, and public API surface
  • JsonType now adapts: read returns string in read String mode; write serializes to string in write String mode; Binary write supports only registered POCOs and throws for string/JsonNode
  • Auto-sets input_format_binary_read_json_as_string/output_format_binary_write_json_as_string via URI when modes demand
  • Updates tests: new JsonModeTests, adjusted bulk copy JSON tests, serialization tests exclude Json; fixes int/long expectations; extensive roundtrip and error-path coverage
  • Adds examples for JSON type usage and read-only users (using JsonWriteMode=None); updates release notes accordingly

Written by Cursor Bugbot for commit ceb8332. This will update automatically on new commits. Configure here.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds configurable JSON handling modes for ClickHouse JSON type operations through new JsonReadMode and JsonWriteMode settings. The default write behavior has changed from binary encoding to string serialization to minimize upgrade impact.

Changes:

  • Introduces JsonReadMode (Binary/String) and JsonWriteMode (Binary/String) enums with connection string support
  • Changes default JsonWriteMode from Binary to String (breaking change, but maintains compatibility)
  • Binary write mode now requires explicit type registration for POCOs
  • Adds comprehensive test coverage for all mode combinations and roundtrip scenarios

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
ClickHouse.Driver/Json/JsonReadMode.cs New enum defining Binary (default) and String read modes
ClickHouse.Driver/Json/JsonWriteMode.cs New enum defining Binary and String write modes, with String as default
ClickHouse.Driver/Types/JsonType.cs Implements mode-dependent read/write logic, enforces Binary mode restrictions
ClickHouse.Driver/TypeSettings.cs Adds JsonReadMode and JsonWriteMode fields to settings record
ClickHouse.Driver/ADO/ClickHouseConnection.cs Injects server settings based on JSON modes (output_format_binary_write_json_as_string, input_format_binary_read_json_as_string)
ClickHouse.Driver/ADO/ClickHouseConnectionStringBuilder.cs Adds JsonReadMode and JsonWriteMode properties with enum parsing
ClickHouse.Driver/ADO/ClickHouseClientSettings.cs Adds JsonReadMode and JsonWriteMode properties, updates Equals/GetHashCode
ClickHouse.Driver.Tests/Types/JsonTypeTests.cs Updates existing tests to use Binary mode where needed, adds mode-specific test names
ClickHouse.Driver.Tests/Types/JsonModeTests.cs New comprehensive test suite covering all mode combinations and scenarios
ClickHouse.Driver.Tests/BulkCopy/BulkCopyTests.cs Updates JSON tests to use appropriate write modes
examples/DataTypes_005_JsonType.cs New example demonstrating all JSON mode combinations with POCOs
RELEASENOTES.md Documents breaking change with migration table and attribute behavior differences

Comment thread ClickHouse.Driver/ADO/ClickHouseConnectionStringBuilder.cs
Comment thread ClickHouse.Driver/Types/JsonType.cs
Comment thread examples/DataTypes_005_JsonType.cs Outdated
Comment thread examples/DataTypes_005_JsonType.cs Outdated
Comment thread examples/DataTypes_005_JsonType.cs Outdated
Comment thread ClickHouse.Driver.Tests/Types/JsonTypeTests.cs Outdated
Comment thread ClickHouse.Driver.Tests/BulkCopy/BulkCopyTests.cs
Comment thread ClickHouse.Driver/ADO/ClickHouseClientSettings.cs
@codecov
Copy link
Copy Markdown

codecov bot commented Jan 22, 2026

Codecov Report

❌ Patch coverage is 97.95918% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
ClickHouse.Driver/Types/JsonType.cs 91.66% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@alex-clickhouse alex-clickhouse marked this pull request as ready for review January 22, 2026 18:37
Comment thread ClickHouse.Driver.Tests/Utilities/TestUtilities.cs
Copy link
Copy Markdown
Contributor

@mzitnik mzitnik left a comment

Choose a reason for hiding this comment

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

General question. Can we call InitAsync from WriteToServerAsync only once

await bulkCopy.InitAsync();
await bulkCopy.WriteToServerAsync([new object[] { 1u, data }]);


// ClickHouse 25.3 returns numbers as strings in this scenario
if (TestUtilities.ServerVersion == Version.Parse("25.3"))
Assert.That(int.Parse(parsed["age"].ToString()), Is.EqualTo(30));
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.

Should we add implicit conversion to numbers if possible for this version (so it will be easy for user client )

Copy link
Copy Markdown
Collaborator Author

@alex-clickhouse alex-clickhouse Jan 26, 2026

Choose a reason for hiding this comment

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

With this setting enabled, the client just returns a plain string. So it basically looks like:

  • 25.3: "{"a": "123"}"
  • Later version: "{"a": 123}"

So there's no place for us to do a conversion here, it's up to the end user to handle the string in whatever way they want. We also don't have any type info.

Comment thread ClickHouse.Driver.Tests/Types/JsonModeTests.cs
Comment thread examples/Advanced_009_ReadOnlyUsers.cs Outdated
@alex-clickhouse
Copy link
Copy Markdown
Collaborator Author

General question. Can we call InitAsync from WriteToServerAsync only once

Good idea, yeah we could hide the InitAsync call inside the WriteToServerAsync() and make sure it's only done once...would be more convenient. Let's do that in a separate PR though.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Comment thread ClickHouse.Driver/Types/JsonType.cs
@alex-clickhouse alex-clickhouse merged commit 481ed15 into main Jan 26, 2026
18 checks passed
@alex-clickhouse alex-clickhouse deleted the json-read-write-modes branch January 26, 2026 13:40
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.

First-class support for input_format_binary_read_json_as_string

3 participants