Skip to content

nlohmann_json: add configuration options - #30784

Open
vic-elgato wants to merge 1 commit into
conan-io:masterfrom
vic-elgato:package/nlohmann-json-options
Open

nlohmann_json: add configuration options#30784
vic-elgato wants to merge 1 commit into
conan-io:masterfrom
vic-elgato:package/nlohmann-json-options

Conversation

@vic-elgato

Copy link
Copy Markdown

Summary

Changes to recipe: nlohmann_json/all versions

Motivation

nlohmann/json is configured almost entirely through preprocessor macros (e.g. implicit conversion, enable exceptions, extended diagnostics etc). The recipe didn't expose any of them, so the only way to change that behavior was to define the macros by hand in your own package.

That works, but it has to be repeated in every consumer and it's easy to get wrong: the macros have to be defined consistently everywhere the headers are included, and some of them (JSON_DIAGNOSTICS in particular) change the layout of basic_json. Being able to set this once as a Conan option, or in a profile, is a lot harder to get wrong and helps especially with shared dependencies across packages.

Details

Adds an option per documented configuration macro, all defaulting to the same behavior as before, so nothing changes unless you set one. Since the macros were introduced in different releases, config_options() drops the ones a given version doesn't know about, and setting them there fails with "option doesn't exist" instead of quietly doing nothing.

Worth noting for review: the value macros are defined also when left at their default rather than only when they differ from the header default. That keeps the behavior pinned to the option, and makes a disagreement with a package that defines the same macro itself show up as a macro redefinition warning instead of one value silently winning on link order.

json-schema-validator does this today with JSON_DIAGNOSTICS, and should switch to the new option once this is in.

New options (see: https://json.nlohmann.me/features/macros/):

option macro
enable_exceptions JSON_NOEXCEPTION
enable_io JSON_NO_IO
enable_implicit_conversions JSON_USE_IMPLICIT_CONVERSIONS
enable_enum_serialization JSON_DISABLE_ENUM_SERIALIZATION
enable_diagnostics JSON_DIAGNOSTICS
enable_diagnostic_positions JSON_DIAGNOSTIC_POSITIONS
enable_global_udls JSON_USE_GLOBAL_UDLS
enable_legacy_discarded_value_comparison JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON

  • Read the contributing guidelines
  • Checked that this PR is not a duplicate: list of PRs by recipe
  • If this is a bug fix, please link related issue or provide bug details
  • Tested locally with at least one configuration using a recent version of Conan

Add a 👍 reaction to pull requests you find important to help the team prioritize, thanks!

@jcar87

jcar87 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Hi @vic-elgato

Unfortunately I dont think these options are something we would accept

The recipe didn't expose any of them, so the only way to change that behavior was to define the macros by hand in your own package.

That would be the expected behaviour because it matches what the nlohmann documentation describes: https://json.nlohmann.me/features/macros/ - it says the following:

Some aspects of the library can be configured by defining preprocessor macros before including the json.hpp header.

So to me it sounds like this isn't something the recipe should be doing automatically for consumers, but rather, something that consumer needs to do at inclusion time, simply as is documented.

We've had issues in the past with recipes that do exactly what you are proposing, impeding users who actually want different translation units on the consumer side to be built with different macros. We would go from a single package that can satisfy those uses cases, to a package that sets options it for the entire graph.

@vic-elgato

Copy link
Copy Markdown
Author

Hi @jcar87

Thanks for the explanation, and I get the concern about not blocking people who configure things per translation unit.

Where I'm coming from is that these macros don't really behave like purely local choices. JSON_DIAGNOSTICS and JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON are explicitly part of the inline-namespace ABI tag, which upstream added because those configurations affect ABI compatibility. A mismatch there gives the configurations different type/symbol identities.

The remaining configuration macros aren't encoded in the ABI namespace, but that doesn't necessarily make differing configurations between TUs safe. They can result in different definitions or available APIs for header-defined entities while still using the same nlohmann::json_abi_... namespace. Nothing necessarily diagnoses such a mismatch at link time, so this can turn into ODR violations or other undefined behavior that happens to work most of the time.

It also isn't only my own code once other packages pull the nlohmann headers into my TUs. For example, json-schema-validator exposes nlohmann types through transitive_headers and already emits JSON_DIAGNOSTICS=1 through cpp_info.defines. So this configuration already crosses package boundaries today, just without giving the consumer a way to explicitly configure the matching side. Similarly, disabling things like I/O, global UDLs, or implicit conversions can make dependency headers incompatible if they rely on those APIs.

For the per-TU case itself, I don't think the added options prevent it. They're still plain macros, so a TU that wants a different value can still redefine it before including the header. The Conan options are a baseline for the package graph, not a lock, and their defaults match upstream, so nothing changes for consumers who don't set them.

For reference, #30752 (stduuid) went in yesterday with the same shape: header-only, with options mapped to cpp_info.defines.

If you'd still rather not have these in the recipe I understand, I mainly wanted to lay out the reasoning behind it.

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.

2 participants