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
7 changes: 4 additions & 3 deletions include/simdjson/generic/ondemand/amalgamated.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include "simdjson/generic/ondemand/raw_json_string.h"
#include "simdjson/generic/ondemand/parser.h"

// JSON builder - needed for extract_into functionality
#include "simdjson/generic/ondemand/json_string_builder.h"

// All other declarations
#include "simdjson/generic/ondemand/array.h"
#include "simdjson/generic/ondemand/array_iterator.h"
Expand Down Expand Up @@ -45,9 +48,7 @@
#include "simdjson/generic/ondemand/token_iterator-inl.h"
#include "simdjson/generic/ondemand/value_iterator-inl.h"

// JSON builder, ideally they should not be part of the ondemand directory
// but it is convenient for now to have them here.
#include "simdjson/generic/ondemand/json_string_builder.h"
// JSON builder inline definitions
#include "simdjson/generic/ondemand/json_string_builder-inl.h"
#include "simdjson/generic/ondemand/json_builder.h"

50 changes: 50 additions & 0 deletions include/simdjson/generic/ondemand/object-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include "simdjson/generic/ondemand/raw_json_string.h"
#include "simdjson/generic/ondemand/json_iterator.h"
#include "simdjson/generic/ondemand/value-inl.h"
#if SIMDJSON_STATIC_REFLECTION
#include "simdjson/generic/ondemand/json_string_builder.h" // for internal::fixed_string
#include <meta>
#endif
#endif // SIMDJSON_CONDITIONAL_INCLUDE

namespace simdjson {
Expand Down Expand Up @@ -195,6 +199,52 @@ simdjson_inline simdjson_result<bool> object::reset() & noexcept {
return iter.reset_object();
}

#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION

template<builder::internal::fixed_string... FieldNames, typename T>
requires(std::is_class_v<T> && (sizeof...(FieldNames) > 0))
simdjson_inline error_code object::extract_into(T& out) & noexcept {
// Helper to check if a field name matches any of the requested fields
auto should_extract = [](std::string_view field_name) constexpr -> bool {
return ((FieldNames.view() == field_name) || ...);
};

// Iterate through all members of T using reflection
template for (constexpr auto mem : std::define_static_array(
std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {

if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));

// Only extract this field if it's in our list of requested fields
if constexpr (should_extract(key)) {
// Try to find and extract the field
if constexpr (concepts::optional_type<decltype(out.[:mem:])>) {
// For optional fields, it's ok if they're missing
auto field_result = find_field_unordered(key);
if (!field_result.error()) {
auto error = field_result.get(out.[:mem:]);
if (error && error != NO_SUCH_FIELD) {
return error;
}
} else if (field_result.error() != NO_SUCH_FIELD) {
return field_result.error();
} else {
out.[:mem:].reset();
}
} else {
// For required fields (in the requested list), fail if missing
SIMDJSON_TRY((*this)[key].get(out.[:mem:]));
}
}
}
};

return SUCCESS;
}

#endif // SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION

} // namespace ondemand
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace simdjson
Expand Down
33 changes: 33 additions & 0 deletions include/simdjson/generic/ondemand/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "simdjson/generic/ondemand/base.h"
#include "simdjson/generic/implementation_simdjson_result_base.h"
#include "simdjson/generic/ondemand/value_iterator.h"
#if SIMDJSON_STATIC_REFLECTION && SIMDJSON_SUPPORTS_CONCEPTS
#include "simdjson/generic/ondemand/json_string_builder.h" // for builder::internal::fixed_string
#endif
#endif // SIMDJSON_CONDITIONAL_INCLUDE

namespace simdjson {
Expand Down Expand Up @@ -231,6 +234,36 @@ class object {
SIMDJSON_TRY(get<T>(out));
return out;
}

#if SIMDJSON_STATIC_REFLECTION
/**
* Extract only specific fields from the JSON object into a struct.
*
* This allows selective deserialization of only the fields you need,
* potentially improving performance by skipping unwanted fields.
*
* Example:
* ```c++
* struct Car {
* std::string make;
* std::string model;
* int year;
* double price;
* };
*
* Car car;
* object.extract_into<"make", "model">(car);
* // Only 'make' and 'model' fields are extracted from JSON
* ```
*
* @tparam FieldNames Compile-time string literals specifying which fields to extract
* @param out The output struct to populate with selected fields
* @returns SUCCESS on success, or an error code if a required field is missing or has wrong type
*/
template<builder::internal::fixed_string... FieldNames, typename T>
requires(std::is_class_v<T> && (sizeof...(FieldNames) > 0))
simdjson_inline error_code extract_into(T& out) & noexcept;
#endif // SIMDJSON_STATIC_REFLECTION
#endif // SIMDJSON_SUPPORTS_CONCEPTS
protected:
/**
Expand Down
Loading
Loading