Skip to content

feat: support more map key type#67

Open
WangFengtu1996 wants to merge 4 commits into
injae:mainfrom
WangFengtu1996:main
Open

feat: support more map key type#67
WangFengtu1996 wants to merge 4 commits into
injae:mainfrom
WangFengtu1996:main

Conversation

@WangFengtu1996
Copy link
Copy Markdown
Contributor

fix bug
#64 (comment)

@WangFengtu1996
Copy link
Copy Markdown
Contributor Author

@injae

  • Thank you for your prompt response and guidance
  • Following your suggestion, I restarted the submission of the PR to fix the issue. However, the original PR was closed due to confusion

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 20, 2025

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.40%. Comparing base (0882fe2) to head (210eb33).

Files with missing lines Patch % Lines
include/serdepp/serializer.hpp 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #67      +/-   ##
==========================================
- Coverage   57.17%   56.40%   -0.78%     
==========================================
  Files          16       16              
  Lines         439      445       +6     
  Branches       82       82              
==========================================
  Hits          251      251              
- Misses        138      144       +6     
  Partials       50       50              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@WangFengtu1996
Copy link
Copy Markdown
Contributor Author

@injae
Do i need to fix fail codeconv failling checks ?

@injae
Copy link
Copy Markdown
Owner

injae commented Dec 22, 2025

@injae Do i need to fix fail codeconv failling checks ?

The reason Codecov failed seems to be that the test coverage dropped compared to before.
It would be good to add tests for this PR.

Comment thread include/serdepp/serializer.hpp Outdated
Comment on lines +479 to +533
namespace detail {
template <typename T>
std::string to_string(const T& key) {
if constexpr (std::is_arithmetic_v<T>) {
return std::to_string(key);
} else {
std::ostringstream oss;
oss << key;
return oss.str();
}
}
}
template <typename K, typename = void>
struct from_string {
static K from(const std::string& key) {
K result;
std::stringstream ss(key);
ss >> result;
if (ss.fail()) {
throw std::runtime_error("Cannot convert JSON key to type " + std::string(typeid(K).name()));
}
return result;
}
};


template <>
struct from_string<std::string> {
static std::string from(const std::string& key) {
return key;
}
};

template <typename K>
struct from_string<K, std::enable_if_t<std::is_integral_v<K> && !std::is_same_v<K, bool>>> {
static K from(const std::string& key) {
return static_cast<K>(std::stoll(key));
}
};

template <>
struct from_string<bool> {
static bool from(const std::string& key) {
if (key == "true" || key == "1") return true;
if (key == "false" || key == "0") return false;
throw std::invalid_argument("Invalid boolean key: " + key);
}
};

template <typename K>
struct from_string<K, std::enable_if_t<std::is_enum_v<K>>> {
static K from(const std::string& key) {
return static_cast<K>(std::stoi(key));
}
};
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Instead of using that specialization, it would be better to use Serde’s serialize and deserialize.

Comment on lines +538 to +558
constexpr inline static auto from(serde_ctx& ctx, T& data, std::string_view key) {
using key_type = typename T::key_type;
using new_T = std::unordered_map<std::string, typename T::mapped_type>;
new_T map_data;
serde_adaptor<typename serde_ctx::Adaptor, new_T, type::map_t>::from(ctx.adaptor, key, map_data);
std::transform(map_data.begin(), map_data.end(), std::inserter(data, data.begin()),
[](const auto& pair) {
return std::make_pair(from_string<key_type>::from(pair.first), pair.second);
});
ctx.read();
}
constexpr inline static auto into(serde_ctx& ctx, const T& data, std::string_view key) {

using value_type = typename T::mapped_type;
using new_T = std::unordered_map<std::string, value_type>;
new_T map_data;
std::transform(data.begin(), data.end(), std::inserter(map_data, map_data.begin()),
[](const auto& pair) {
return std::make_pair(detail::to_string(pair.first), pair.second);
});
serde_adaptor<typename serde_ctx::Adaptor, new_T, type::map_t>::into(ctx.adaptor, key, map_data);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

It seems that we may need to revisit the current approach for implementing T <-> string conversions in the serde core.

There appears to be a small issue with the direction I suggested previously. After giving it some more thought, I think the approach where each adapter is responsible for its own implementation—similar to the adapter you implemented in the previous PR—might be a better and cleaner solution overall.

With the current approach, I see a couple of concerns:

  1. Implementing this would require introducing STL containers into the serdepp core.

    I do understand why using unordered_map is effectively unavoidable in this case
    (according to the C++ specification, when T = M<K, V>, we can extract K and V, but not M itself, which makes it impossible to construct something like M<string, V>).

    That said, serdepp currently tries to intentionally avoid using STL containers in the core library.
    In the C++ ecosystem, it’s fairly common to rely on spec-compatible custom implementations instead of STL containers, often due to performance considerations.

  2. This approach would make serdepp less adapter-neutral.

    Serdepp was originally designed with the goal of supporting adapters that are not necessarily JSON-compatible.
    From that perspective, implementing it this way might go slightly against that original intention.

In summary:

It might be better to delegate the responsibility for T <-> key support to the adapter itself.
Rather than adding a separate to_string specialization in the core, we could rely on the existing serde serialize and deserialize implementations that adapters already provide.

Additionally, it could be helpful to introduce shared utility functions for this behavior, so that different adapters can reuse the same logic where appropriate.

Additionally, since we’re currently using squash merges, it should be fine to make the changes in this PR.

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