nlohmann / json

JSON for Modern C++
https://json.nlohmann.me
MIT License
42.01k stars 6.63k forks source link

Incompatible with C++20 modules in MSVC #3970

Open andylizf opened 1 year ago

andylizf commented 1 year ago

Description

Importing a module file using the lib will cause a compilation error.

Reproduction steps

Codes below.

Expected vs. actual results

To compile successfully.

Minimal code example

network.ixx:

module;
#include <nlohmann/json.hpp>
#include <string>
export module network;
using nlohmann::json;
export struct message {
  message(std::string str) { json doc = json::parse(str); }
};

main.cpp:

import network;
int main() { message msg(R"({"hello": "world"})"); }

Error messages

nlohmann\json.hpp(117): error C2039: 'json_sax_dom_callback_parser': is not a member of 'nlohmann::json_abi_v3_11_2::detail'
nlohmann\detail\output\serializer.hpp(35): note: see declaration of 'nlohmann::json_abi_v3_11_2::detail'
main.cpp(3): note: see reference to class template instantiation 'nlohmann::json_abi_v3_11_2::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char>>,bool,int64_t,uint64_t,double,std::allocator,nlohmann::json_abi_v3_11_2::adl_serializer,std::vector<uint8_t,std::allocator<uint8_t>>>' being compiled
nlohmann\byte_container_with_subtype.hpp(101): warning C4820: 'nlohmann::json_abi_v3_11_2::byte_container_with_subtype<BinaryType>': '7' bytes padding added after data member 'nlohmann::json_abi_v3_11_2::byte_container_with_subtype<BinaryType>::m_has_subtype'
        with
        [
            BinaryType=std::vector<uint8_t,std::allocator<uint8_t>>
        ]
        [            BinaryType=std::vector<uint8_t,std::allocator<uint8_t>>
        ]
nlohmann\json.hpp(4187): warning C4820: 'nlohmann::json_abi_v3_11_2::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char>>,bool,int64_t,uint64_t,double,std::allocator,nlohmann::json_abi_v3_11_2::adl_serializer,std::vector<uint8_t,std::allocator<uint8_t>>>': '7' bytes padding added after data member 'nlohmann::json_abi_v3_11_2::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char>>,bool,int64_t,uint64_t,double,std::allocator,nlohmann::json_abi_v3_11_2::adl_serializer,std::vector<uint8_t,std::allocator<uint8_t>>>::m_type

Compiler and operating system

Visual Studio 17 2022 MSVC 19.36.32323; Windows-10.0.22624

Library version

3.11.2

Validation

nlohmann commented 1 year ago

Maybe related to #3974 and fixed by #3975.

andylizf commented 1 year ago

Is it fixed now? BTW, how to use the new version in xmake?

gviot commented 1 year ago

it's not fixed, I got this compilation error as well with single include and modules. It looks kinda weird, not sure why this line in particular errors but not the one above which is almost identical.

kiraYuukiAsuna commented 6 months ago

same issue in version 3.11.3

rnikander commented 6 months ago

I have the issue, 3.11.3, Visual Studio, using C++20 modules.

rioki commented 3 months ago

The issue is not an issue with nlohmann/json, but rather MSVC compiler. I get the same issue with c42f/tinyformat. The compiler does not like something in the header and I just have not yet figured out what it is.

You can work around it if you add a "compilation firewall" by defining an interface in a header and shoving the include in a regular cpp. Too bad both libraries rely heavily on template to make the client code nice and small.

JamieSharpe commented 3 months ago

I'm having a similar issue when trying to include nlohmann/json.hpp within a C++ module file.

Dev Attribube Value
Visual Studio Version: 17.10.0 Preview 7.0
Windows SDK Version: 10.0
Platform Toolset: Visual Studio 2022 (v143)
C++ Language Standard: Preview - Features from the Latest C++ Working Draft (/std:c++latest)
nlohmann-json Version: 3.11.3

The following section of my code:

nlohmann::json config = {
    {"Version", "x.x.x.d"}
};

Provides the error:

>Main.cpp
> *\vcpkg_installed\x64 - windows\x64 - windows\include\nlohmann\json.hpp(120, 38) : error C2039 : 'json_sax_dom_callback_parser' : is not a member of 'nlohmann::json_abi_v3_11_3::detail'

I'm in a greenfield project and would love to be able to use this library to parse and export json data.

@rioki, are you able to expand on your temporary fix until either this library or MSVC have a solution?

Many thanks.

rnikander commented 3 months ago

For my project I moved to jsoncpp, which has been working fine with a module wrapper that I made.

rioki commented 2 months ago

@JamieSharpe I dropped modules altogether for the time being. I ran into 1001 issues like this. I will revisit modules in a year or two. Looks promising, not there yet.

duerrbaby commented 1 month ago

The issue is not an issue with nlohmann/json, but rather MSVC compiler. I get the same issue with c42f/tinyformat. The compiler does not like something in the header and I just have not yet figured out what it is.

You can work around it if you add a "compilation firewall" by defining an interface in a header and shoving the include in a regular cpp. Too bad both libraries rely heavily on template to make the client code nice and small.

Exactly how did you implement the compilation firewall? Perhaps you can show some code. I'm getting compilation errors when I try to do it. :/

Blechwolf commented 4 weeks ago

Exactly how did you implement the compilation firewall? Perhaps you can show some code. I'm getting compilation errors when I try to do it. :/

For me the following works:

JSONTools.ixx

module;

#include <filesystem>

export module JSONTools;

import DataDefs;  // defines A

namespace myns
{
    export class JSONTools final
    {
        public:
            static A readA(const std::filesystem::path& filePath);
            static void writeA(const std::filesystem::path& filePath, const A& a);
        private:
            JSONTools() = delete;
            JSONTools(const JSONTools&) = delete;
            JSONTools(JSONTools&&) = delete;
    };    

} // namespace myns

DataDefs.cpp

module;

#include <fstream>
#include <nlohmann/json.hpp>

module JSONTools;

import DataDefs;

namespace myns
{

    A JSONTools::readA(const std::filesystem::path& filePath);
    {
        std::string fileContent = readTxt(filePath);   // readTxt defined somewhere else
        nlohmann::json jsonContent = nlohmann::json::parse(fileContent);

        A result{};

        A.setVersion(jsonContent["version"].get<int>());

        // Fill A with the data read from the json

        return result;
    }

    void JSONTools::writeA(const std::filesystem::path& filePath, const A& a);
    {
        auto oFile = std::make_unique<std::ofstream>(filePath, std::ios::ate);

        nlohmann::json jsonOutput;

        jsonOutput["version"] = 1;
        // add some more content to json file

        (*oFile) << jsonOutput; 
    }

} // myns

CMakeLists.txt

project(JSONTools CXX)

find_package(nlohmann_json CONFIG REQUIRED)

set(INTERFACE_LIST
   JSONTools.ixx
)

set(SOURCE_LIST
   DataDefs.cpp
)

add_library(${PROJECT_NAME})

target_sources(${PROJECT_NAME}
   PRIVATE
      ${SOURCE_LIST}
   PUBLIC
   FILE_SET CXX_MODULES
   FILES ${INTERFACE_LIST}
)

target_link_libraries(${PROJECT_NAME}
PRIVATE
   DataDefs
   nlohmann_json::nlohmann_json
)

For every other module I am just importing JSONTools in the target_link_libraries section of the corresponding CMakeLists.txt