JsonObjectCompact¶
JsonObjectCompact represents mutable JSON objects (key-value mappings) in the Hakka JSON library. Unlike primitive types which use value deduplication, objects are mutable containers that store key-value pairs with Python dict-like behavior.
Header: include/hakka_json_object.hpp
Architecture¶
JsonObjectCompact is a mutable container type with the following characteristics:
- Storage: Two
JsonArrayCompactinstances (keys array and values array stored as handles) - Key Lookup: O(n) linear search using the
find()method - Mutability: Objects can be modified after creation (unlike immutable primitive types)
- No Deduplication: Each object instance maintains its own storage
- CRTP Pattern: Inherits from
JsonStructuredCompact<JsonObjectCompact>for compile-time polymorphism - Reference Counting: Atomic reference counting for Python FFI integration
- Handle Management: Managed by
ObjectManagerCompactwith type mask0xC0000000 - Dict-like Behavior: Provides Python dict-like operations (pop, popitem, setdefault, update, fromkeys)
Note
Objects use two parallel arrays for storage: one for keys (strings) and one for values. Key lookup is O(n) linear search, not hash-based.
Factory Methods¶
create¶
[[nodiscard]] static JsonHandleCompact create();
Creates an empty JSON object.
-
Parameters:
- None.
-
Returns:
- A
JsonHandleCompactreferencing a new empty object.
- A
-
Error Handling:
- Returns invalid handle if allocation fails.
- Exception safety: Strong guarantee.
-
Complexity:
- O(1) amortized time complexity (may trigger vector reallocation).
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); assert(object.get_type() == HAKKA_JSON_OBJECT);
create_unique¶
[[nodiscard]] static std::unique_ptr<JsonObjectCompact> create_unique();
Creates an empty JSON object as a unique pointer for direct ownership.
-
Parameters:
- None.
-
Returns:
- A
std::unique_ptr<JsonObjectCompact>owning a new empty object.
- A
-
Error Handling:
- Returns
nullptrif allocation fails. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object_ptr = JsonObjectCompact::create_unique(); assert(object_ptr != nullptr);
loads (std::string)¶
static tl::expected<JsonHandleCompact, HakkaJsonResultEnum> loads(const std::string &json_str, uint32_t max_depth = 2048);
Deserializes a JSON string into a JsonObjectCompact instance.
-
Parameters:
json_str: The JSON string to deserialize.max_depth: Maximum recursion depth for nested structures (default: 2048).
-
Returns:
- On success: A
JsonHandleCompactcontaining the deserialized object. - On failure:
HAKKA_JSON_TYPE_ERRORif the JSON is not an object,HAKKA_JSON_RECURSION_DEPTH_EXCEEDEDif max depth is exceeded, or other parsing errors.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORif the root JSON value is not an object. - Returns
HAKKA_JSON_RECURSION_DEPTH_EXCEEDEDif nesting exceedsmax_depth. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity where n is the length of the JSON string.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
std::string json_str = R"({"key": "value"})"; auto object = JsonObjectCompact::loads(json_str); if (object) { auto view = object.value().get_view(); auto* obj = std::get<const JsonObjectCompact*>(view); assert(obj->length() == 1); }
loads (std::string_view)¶
static tl::expected<JsonHandleCompact, HakkaJsonResultEnum> loads(std::string_view json_str, uint32_t max_depth = 2048);
Deserializes a JSON string view into a JsonObjectCompact instance.
-
Parameters:
json_str: The JSON string view to deserialize.max_depth: Maximum recursion depth for nested structures (default: 2048).
-
Returns:
- On success: A
JsonHandleCompactcontaining the deserialized object. - On failure:
HAKKA_JSON_TYPE_ERRORif the JSON is not an object,HAKKA_JSON_RECURSION_DEPTH_EXCEEDEDif max depth is exceeded, or other parsing errors.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORif the root JSON value is not an object. - Returns
HAKKA_JSON_RECURSION_DEPTH_EXCEEDEDif nesting exceedsmax_depth. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity where n is the length of the JSON string.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
const char json_str[] = R"({"key1": 42})"; auto object = JsonObjectCompact::loads(std::string_view(json_str, sizeof(json_str) - 1)); if (object) { auto view = object.value().get_view(); auto* obj = std::get<const JsonObjectCompact*>(view); assert(obj->length() == 1); }
Serialization Methods¶
dump¶
tl::expected<std::string, HakkaJsonResultEnum> dump(uint32_t max_depth = 0) const;
Serializes the object to a JSON string.
-
Parameters:
max_depth: Maximum recursion depth for nested structures (0 means no limit).
-
Returns:
- On success: A
std::stringcontaining the JSON representation. - On failure:
HAKKA_JSON_RECURSION_DEPTH_EXCEEDEDif max depth is reached,HAKKA_JSON_INTERNAL_ERRORon exception.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_RECURSION_DEPTH_EXCEEDEDwhenmax_depthis exceeded. - Returns
HAKKA_JSON_INTERNAL_ERRORif string allocation throws an exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity where n is the total number of key-value pairs including nested structures.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto view = object.get_view(); auto* obj_view = std::get<const JsonObjectCompact*>(view); auto result = obj_view->dump(512); if (result) { std::cout << result.value() << std::endl; // Output: {"key": 42} }
to_bytes¶
HakkaJsonResultEnum to_bytes(char *buffer, uint32_t *buffer_size) const;
Serializes the object into a null-terminated byte buffer.
-
Parameters:
buffer: Pointer to the destination byte buffer.buffer_size: Pointer to the buffer size. On input, specifies the buffer capacity. On output, contains the number of bytes written (excluding null terminator) or the required size if buffer is too small.
-
Returns:
HAKKA_JSON_SUCCESSif serialization succeeds.HAKKA_JSON_NOT_ENOUGH_MEMORYif the buffer is too small. The required size is written to*buffer_size.HAKKA_JSON_INTERNAL_ERRORif an exception occurs.
-
Error Handling:
- Returns
HAKKA_JSON_NOT_ENOUGH_MEMORYwhen buffer capacity is insufficient. - Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity where n is the total number of key-value pairs including nested structures.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); char buffer[512]; uint32_t size = sizeof(buffer); auto view = object.get_view(); auto* obj_view = std::get<const JsonObjectCompact*>(view); auto result = obj_view->to_bytes(buffer, &size); if (result == HAKKA_JSON_SUCCESS) { std::cout << buffer << std::endl; // Output: {"key": 42} }
dump_size¶
uint64_t dump_size() const;
Returns the size of the serialized JSON string representation.
-
Parameters:
- None.
-
Returns:
- The number of bytes required to serialize the object (excluding null terminator).
-
Error Handling:
- Returns
0on internal errors. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity where n is the total number of key-value pairs including nested structures.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto view = object.get_view(); auto* obj_view = std::get<const JsonObjectCompact*>(view); uint64_t size = obj_view->dump_size(); std::cout << "Size: " << size << std::endl; // Output: Size: 12 (for {"key": 42})
Type Information Methods¶
type¶
HakkaJsonType type() const;
Returns the JSON type of this instance.
-
Parameters:
- None.
-
Returns:
HAKKA_JSON_OBJECT
-
Error Handling:
- None.
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); HakkaJsonType t = object.get_type(); assert(t == HAKKA_JSON_OBJECT);
Comparison Methods¶
compare¶
tl::expected<int, HakkaJsonResultEnum> compare(const JsonHandleCompact &other) const;
Compares this object with another JSON value. Objects are compared by iterating through keys in insertion order and comparing corresponding values.
-
Parameters:
other: TheJsonHandleCompactto compare against.
-
Returns:
- On success: An integer comparison result:
< 0if this object is less thanother0if this object equalsother> 0if this object is greater thanother
- On failure:
HAKKA_JSON_TYPE_ERRORifotheris not an object or if value types mismatch.
- On success: An integer comparison result:
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORifotheris notHAKKA_JSON_OBJECT. - Returns
HAKKA_JSON_TYPE_ERRORif corresponding values have different types. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n×m) time complexity where n is the number of key-value pairs to compare and m is the number of key-value pairs in the other object (due to O(m) linear search for each key lookup).
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object1 = JsonObjectCompact::create(); auto object2 = JsonObjectCompact::create(); auto* obj1 = std::get<JsonObjectCompact*>(object1.get_mut_ptr()); auto* obj2 = std::get<JsonObjectCompact*>(object2.get_mut_ptr()); obj1->set("key", JsonIntCompact::create(42)); obj2->set("key", JsonIntCompact::create(42)); auto view1 = object1.get_view(); auto* obj1_view = std::get<const JsonObjectCompact*>(view1); auto result = obj1_view->compare(object2); if (result) { assert(result.value() == 0); // Equal objects }
hash¶
uint64_t hash() const;
Computes the hash value of the object by XORing the hashes of keys and values arrays.
-
Parameters:
- None.
-
Returns:
- A 64-bit hash value.
-
Error Handling:
- None.
- Exception safety: No-throw guarantee.
-
Complexity:
- O(n) time complexity where n is the number of key-value pairs.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto view = object.get_view(); auto* obj_view = std::get<const JsonObjectCompact*>(view); uint64_t h = obj_view->hash(); std::cout << "Hash: " << h << std::endl;
Reference Counting Methods¶
inc_ref¶
uint64_t inc_ref() const;
Increments the reference count atomically.
-
Parameters:
- None.
-
Returns:
- The new reference count after incrementing.
-
Error Handling:
- None.
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe (uses atomic operations with
memory_order_relaxed).
- This function is thread-safe (uses atomic operations with
-
Example:
auto object = JsonObjectCompact::create(); auto view = object.get_view(); auto* obj = std::get<const JsonObjectCompact*>(view); uint64_t count = obj->inc_ref(); std::cout << "New ref count: " << count << std::endl;
dec_ref¶
uint64_t dec_ref() const;
Decrements the reference count atomically.
-
Parameters:
- None.
-
Returns:
- The new reference count after decrementing.
-
Error Handling:
- None.
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe (uses atomic operations with
memory_order_relaxed).
- This function is thread-safe (uses atomic operations with
-
Example:
auto object = JsonObjectCompact::create(); auto view = object.get_view(); auto* obj = std::get<const JsonObjectCompact*>(view); uint64_t count = obj->dec_ref(); std::cout << "New ref count: " << count << std::endl; // Note: Manually calling dec_ref() is not recommended; use Handle system
Warning
Manual reference counting is intended for Python FFI integration. Normal usage should rely on the JsonHandleCompact system for automatic reference management.
Element Access Methods¶
get¶
tl::expected<JsonHandleCompact, HakkaJsonResultEnum> get(KeyType key) const;
Retrieves a value by key or by index. Accepts both string keys and integer indices.
-
Parameters:
key: AKeyTypevariant containing either astd::stringkey or anint64_tindex.
-
Returns:
- On success: A
JsonHandleCompactreferencing the value (for string key) or a[key, value]array (for integer index). - On failure:
HAKKA_JSON_TYPE_ERRORif key type is invalid,HAKKA_JSON_KEY_NOT_FOUNDif string key doesn't exist,HAKKA_JSON_INDEX_OUT_OF_BOUNDSif index is out of range.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORifkeyis neitherstd::stringnorint64_t. - Returns
HAKKA_JSON_KEY_NOT_FOUNDif the string key is not found. - Returns
HAKKA_JSON_INDEX_OUT_OF_BOUNDSif index is out of range. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity for string key lookup (linear search).
- O(1) amortized time complexity for integer index access (creates new array with two elements).
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); // Get by string key auto result = obj->get("key"); if (result) { assert(result.value().get_type() == HAKKA_JSON_INT); } // Get by index (returns [key, value] array) auto result2 = obj->get(KeyType(static_cast<int64_t>(0))); if (result2) { assert(result2.value().get_type() == HAKKA_JSON_ARRAY); }
set¶
HakkaJsonResultEnum set(KeyType key, JsonHandleCompact value) const;
Sets a value for the specified key. If the key exists, updates the value; otherwise, inserts a new key-value pair.
-
Parameters:
key: AKeyTypevariant containing astd::stringkey.value: TheJsonHandleCompactvalue to set.
-
Returns:
HAKKA_JSON_SUCCESSif the operation succeeds.HAKKA_JSON_TYPE_ERRORif key is not a string.HAKKA_JSON_NOT_ENOUGH_MEMORYif allocation fails.HAKKA_JSON_INTERNAL_ERRORon exception.
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORifkeydoes not hold astd::string. - Returns
HAKKA_JSON_NOT_ENOUGH_MEMORYif key handle creation fails. - Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity for key lookup, O(1) amortized for insertion if key doesn't exist.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); auto result = obj->set("key", JsonIntCompact::create(42)); assert(result == HAKKA_JSON_SUCCESS); // Update existing key auto result2 = obj->set("key", JsonIntCompact::create(100)); assert(result2 == HAKKA_JSON_SUCCESS);
at¶
tl::expected<JsonHandleCompact, HakkaJsonResultEnum> at(uint32_t index) const;
Retrieves a key-value pair at the specified index as a [key, value] array.
-
Parameters:
index: The zero-based index of the key-value pair.
-
Returns:
- On success: A
JsonHandleCompactreferencing aJsonArrayCompactcontaining[key, value]. - On failure:
HAKKA_JSON_INDEX_OUT_OF_BOUNDSif index is out of range,HAKKA_JSON_NOT_ENOUGH_MEMORYif allocation fails,HAKKA_JSON_INTERNAL_ERRORon other errors.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_INDEX_OUT_OF_BOUNDSif index >= length. - Returns
HAKKA_JSON_NOT_ENOUGH_MEMORYif array creation fails. - Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(1) amortized time complexity (array creation with two push_back operations).
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto pair = obj->at(0); if (pair) { auto* arr = std::get<const JsonArrayCompact*>(pair.value().get_view()); assert(arr->length() == 2); // [key, value] }
remove¶
HakkaJsonResultEnum remove(KeyType key) const;
Removes a key-value pair by key.
-
Parameters:
key: AKeyTypevariant containing astd::stringkey.
-
Returns:
HAKKA_JSON_SUCCESSif the operation succeeds.HAKKA_JSON_TYPE_ERRORif key is not a string.HAKKA_JSON_KEY_NOT_FOUNDif the key doesn't exist.HAKKA_JSON_INTERNAL_ERRORon exception.
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORifkeydoes not hold astd::string. - Returns
HAKKA_JSON_KEY_NOT_FOUNDif the key is not found. - Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity for key lookup and array element removal.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto result = obj->remove("key"); assert(result == HAKKA_JSON_SUCCESS); assert(obj->length() == 0);
contains¶
bool contains(KeyType key) const;
Checks if a key exists in the object.
-
Parameters:
key: AKeyTypevariant containing astd::stringkey.
-
Returns:
trueif the key exists,falseotherwise.
-
Error Handling:
- Returns
falseif key is not a string or if an exception occurs. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity (linear search through keys).
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); assert(obj->contains("key") == true); assert(obj->contains("missing") == false);
Object Manipulation Methods¶
insert¶
HakkaJsonResultEnum insert(KeyType key, JsonHandleCompact value) const;
Inserts a new key-value pair. Unlike set(), this always appends without checking for existing keys.
-
Parameters:
key: AKeyTypevariant containing astd::stringkey.value: TheJsonHandleCompactvalue to insert.
-
Returns:
HAKKA_JSON_SUCCESSif the operation succeeds.HAKKA_JSON_TYPE_ERRORif key is not a string.HAKKA_JSON_NOT_ENOUGH_MEMORYif allocation fails.HAKKA_JSON_INTERNAL_ERRORon exception.
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORifkeydoes not hold astd::string. - Returns
HAKKA_JSON_NOT_ENOUGH_MEMORYif key handle creation fails. - Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(1) amortized time complexity (appends to arrays).
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); auto result = obj->insert("key", JsonIntCompact::create(42)); assert(result == HAKKA_JSON_SUCCESS);
erase¶
HakkaJsonResultEnum erase(KeyType key) const;
Removes a key-value pair by key. This is an alias for remove().
-
Parameters:
key: AKeyTypevariant containing astd::stringkey.
-
Returns:
HAKKA_JSON_SUCCESSif the operation succeeds.HAKKA_JSON_TYPE_ERRORif key is not a string.HAKKA_JSON_KEY_NOT_FOUNDif the key doesn't exist.HAKKA_JSON_INTERNAL_ERRORon exception.
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORifkeydoes not hold astd::string. - Returns
HAKKA_JSON_KEY_NOT_FOUNDif the key is not found. - Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity for key lookup and array element removal.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto result = obj->erase("key"); assert(result == HAKKA_JSON_SUCCESS);
clear¶
HakkaJsonResultEnum clear() const;
Removes all key-value pairs from the object.
-
Parameters:
- None.
-
Returns:
HAKKA_JSON_SUCCESSif the operation succeeds.HAKKA_JSON_INTERNAL_ERRORon exception.
-
Error Handling:
- Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity where n is the number of key-value pairs.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key1", JsonIntCompact::create(42)); obj->set("key2", JsonIntCompact::create(100)); auto result = obj->clear(); assert(result == HAKKA_JSON_SUCCESS); assert(obj->length() == 0);
shrink_to_fit¶
void shrink_to_fit() const;
Reduces the capacity of the underlying arrays to match their sizes, releasing unused memory.
-
Parameters:
- None.
-
Returns:
- None.
-
Error Handling:
- Ignores errors (optimization only).
- Exception safety: Strong guarantee.
-
Complexity:
- O(n) time complexity where n is the number of key-value pairs.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); obj->shrink_to_fit(); // Optimize memory usage
pop¶
tl::expected<JsonHandleCompact, HakkaJsonResultEnum> pop(const KeyType &key);
Removes and returns the value associated with the specified key.
-
Parameters:
key: AKeyTypevariant containing astd::stringkey.
-
Returns:
- On success: A
JsonHandleCompactcontaining the removed value. - On failure:
HAKKA_JSON_TYPE_ERRORif key is not a string,HAKKA_JSON_KEY_NOT_FOUNDif the key doesn't exist,HAKKA_JSON_INTERNAL_ERRORon exception.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORifkeydoes not hold astd::string. - Returns
HAKKA_JSON_KEY_NOT_FOUNDif the key is not found. - Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity for key lookup and removal.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto result = obj->pop("key"); if (result) { assert(result.value().get_type() == HAKKA_JSON_INT); assert(obj->length() == 0); }
popitem¶
tl::expected<std::pair<KeyType, JsonHandleCompact>, HakkaJsonResultEnum> popitem();
Removes and returns the last key-value pair in insertion order (similar to Python's dict.popitem()).
-
Parameters:
- None.
-
Returns:
- On success: A
std::pair<KeyType, JsonHandleCompact>containing the removed key and value. - On failure:
HAKKA_JSON_KEY_NOT_FOUNDif the object is empty,HAKKA_JSON_INTERNAL_ERRORon exception.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_KEY_NOT_FOUNDif the object is empty. - Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- \(\Theta(1)\) time complexity (always removes last element with no shifting required).
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key1", JsonIntCompact::create(42)); obj->set("key2", JsonIntCompact::create(100)); auto result = obj->popitem(); if (result) { auto [key, value] = result.value(); assert(std::get<std::string>(key) == "key2"); assert(obj->length() == 1); }
setdefault¶
tl::expected<JsonHandleCompact, HakkaJsonResultEnum> setdefault(const KeyType &key, JsonHandleCompact default_value = JsonHandleCompact());
Returns the value for the key if it exists; otherwise, inserts the key with the default value and returns it.
-
Parameters:
key: AKeyTypevariant containing astd::stringkey.default_value: The default value to set if the key doesn't exist (default: invalid handle).
-
Returns:
- On success: A
JsonHandleCompactcontaining the existing or newly set value. - On failure:
HAKKA_JSON_TYPE_ERRORif key is not a string, other errors if insertion fails.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_TYPE_ERRORifkeydoes not hold astd::string. - May return insertion errors if the key doesn't exist and insertion fails.
- Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n) time complexity for key lookup, O(1) amortized for insertion if key doesn't exist.
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); // Key doesn't exist, inserts default value auto result = obj->setdefault("key", JsonIntCompact::create(100)); if (result) { auto view = result.value().get_view(); auto* int_val = std::get<const JsonIntCompact*>(view); assert(std::get<int64_t>(int_val->get().value()) == 100); } // Key exists, returns existing value auto result2 = obj->setdefault("key", JsonIntCompact::create(200)); if (result2) { auto view = result2.value().get_view(); auto* int_val = std::get<const JsonIntCompact*>(view); assert(std::get<int64_t>(int_val->get().value()) == 100); }
update¶
HakkaJsonResultEnum update(const JsonObjectCompact &other);
Updates this object with key-value pairs from another object, overwriting existing keys.
-
Parameters:
other: AJsonObjectCompactreference to merge from.
-
Returns:
HAKKA_JSON_SUCCESSif the operation succeeds.HAKKA_JSON_INTERNAL_ERRORon exception.
-
Error Handling:
- Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Skips invalid keys or values.
- Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n×m) time complexity where n is the number of keys in
otherand m is the number of keys in this object (due to O(m) linear search for each key).
- O(n×m) time complexity where n is the number of keys in
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
auto object1 = JsonObjectCompact::create(); auto object2 = JsonObjectCompact::create(); auto* obj1 = std::get<JsonObjectCompact*>(object1.get_mut_ptr()); auto* obj2 = std::get<JsonObjectCompact*>(object2.get_mut_ptr()); obj1->set("key1", JsonIntCompact::create(42)); obj2->set("key2", JsonIntCompact::create(100)); auto result = obj1->update(*obj2); assert(result == HAKKA_JSON_SUCCESS); assert(obj1->length() == 2); assert(obj1->contains("key1")); assert(obj1->contains("key2"));
fromkeys¶
static tl::expected<JsonHandleCompact, HakkaJsonResultEnum> fromkeys(const std::vector<KeyType> &keys, JsonHandleCompact value);
Creates a new object with the specified keys, all set to the same value.
-
Parameters:
keys: A vector ofKeyTypecontaining string keys.value: TheJsonHandleCompactvalue to assign to all keys.
-
Returns:
- On success: A
JsonHandleCompactcontaining the new object. - On failure:
HAKKA_JSON_NOT_ENOUGH_MEMORYif allocation fails,HAKKA_JSON_INTERNAL_ERRORon exception.
- On success: A
-
Error Handling:
- Returns
HAKKA_JSON_NOT_ENOUGH_MEMORYif object creation fails. - Skips non-string keys.
- Returns
HAKKA_JSON_INTERNAL_ERRORon exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- O(n×m) time complexity where n is the number of keys and m is the average object size during insertion (due to O(m) linear search for each key).
-
Thread Safety:
- This function is NOT thread-safe. External synchronization is required for concurrent access.
-
Example:
std::vector<KeyType> keys = {"key1", "key2", "key3"}; auto default_value = JsonIntCompact::create(0); auto result = JsonObjectCompact::fromkeys(keys, default_value); if (result) { auto* obj = std::get<JsonObjectCompact*>(result.value().get_mut_ptr()); assert(obj->length() == 3); assert(obj->contains("key1")); assert(obj->contains("key2")); assert(obj->contains("key3")); }
Object Information Methods¶
length¶
std::size_t length() const;
Returns the number of key-value pairs in the object.
-
Parameters:
- None.
-
Returns:
- The number of key-value pairs, or
0on error.
- The number of key-value pairs, or
-
Error Handling:
- Returns
0on exception. - Exception safety: Strong guarantee.
- Returns
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); assert(obj->length() == 1);
keys¶
const JsonArrayCompact &keys() const;
Returns a reference to the internal keys array.
-
Parameters:
- None.
-
Returns:
- A const reference to the
JsonArrayCompactcontaining all keys as strings.
- A const reference to the
-
Error Handling:
- None (assumes internal consistency).
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key1", JsonIntCompact::create(42)); obj->set("key2", JsonIntCompact::create(100)); const auto& keys = obj->keys(); assert(keys.length() == 2);
keys_handle¶
JsonHandleCompact keys_handle() const;
Returns a handle to the internal keys array.
-
Parameters:
- None.
-
Returns:
- A
JsonHandleCompactreferencing the keys array.
- A
-
Error Handling:
- None.
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto keys_handle = obj->keys_handle(); assert(keys_handle.get_type() == HAKKA_JSON_ARRAY);
values¶
const JsonArrayCompact &values() const;
Returns a reference to the internal values array.
-
Parameters:
- None.
-
Returns:
- A const reference to the
JsonArrayCompactcontaining all values.
- A const reference to the
-
Error Handling:
- None (assumes internal consistency).
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key1", JsonIntCompact::create(42)); obj->set("key2", JsonIntCompact::create(100)); const auto& values = obj->values(); assert(values.length() == 2);
values_handle¶
JsonHandleCompact values_handle() const;
Returns a handle to the internal values array.
-
Parameters:
- None.
-
Returns:
- A
JsonHandleCompactreferencing the values array.
- A
-
Error Handling:
- None.
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto values_handle = obj->values_handle(); assert(values_handle.get_type() == HAKKA_JSON_ARRAY);
Iterator Methods¶
begin¶
JsonObjectIterCompact begin() const;
Returns a bidirectional iterator to the first key-value pair.
-
Parameters:
- None.
-
Returns:
- A bidirectional iterator pointing to the first key-value pair.
-
Error Handling:
- None.
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key1", JsonIntCompact::create(42)); obj->set("key2", JsonIntCompact::create(100)); for (auto it = obj->begin(); it != obj->end(); ++it) { auto [key, value] = *it; // Process key-value pair }
end¶
JsonObjectIterCompact end() const;
Returns a bidirectional iterator to one past the last key-value pair.
-
Parameters:
- None.
-
Returns:
- A bidirectional iterator pointing to one past the last key-value pair.
-
Error Handling:
- None.
- Exception safety: No-throw guarantee.
-
Complexity:
- \(\Theta(1)\) time complexity.
-
Thread Safety:
- This function is thread-safe for concurrent reads. Concurrent modification requires external synchronization.
-
Example:
auto object = JsonObjectCompact::create(); auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr()); obj->set("key", JsonIntCompact::create(42)); auto it = obj->begin(); assert(it != obj->end());
Storage Architecture¶
Objects in Hakka JSON use a two-array storage model:
struct ObjectType {
JsonHandleCompact keys; // Handle to JsonArrayCompact of strings
JsonHandleCompact values; // Handle to JsonArrayCompact of values
};
Key Characteristics: - Parallel Arrays: Keys and values are stored in separate parallel arrays at the same indices - Insertion Order: Key-value pairs maintain insertion order - Linear Search: Key lookup is O(n) using linear search through the keys array - No Hash Table: Unlike many JSON libraries, this implementation uses arrays instead of hash tables
This design trades lookup performance for memory efficiency and simplicity.
Memory Management¶
Objects are mutable containers that do not use value deduplication:
auto object1 = JsonObjectCompact::create();
auto object2 = JsonObjectCompact::create();
auto* obj1 = std::get<JsonObjectCompact*>(object1.get_mut_ptr());
auto* obj2 = std::get<JsonObjectCompact*>(object2.get_mut_ptr());
obj1->set("key", JsonIntCompact::create(42));
obj2->set("key", JsonIntCompact::create(42));
// object1 and object2 are distinct instances with separate storage
// Modifying object1 does not affect object2
Reference Counting: Objects use atomic reference counting for memory management, designed for Python FFI integration.
Automatic Cleanup: The JsonHandleCompact system manages object lifecycle automatically. Objects are deallocated when the last handle is released.
Python Dict-like Behavior¶
JsonObjectCompact provides operations similar to Python dictionaries:
auto object = JsonObjectCompact::create();
auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr());
// dict[key] = value => obj->set(key, value)
obj->set("key", JsonIntCompact::create(42));
// value = dict[key] => auto value = obj->get(key)
auto value = obj->get("key");
// key in dict => obj->contains(key)
bool exists = obj->contains("key");
// value = dict.pop(key) => auto value = obj->pop(key)
auto popped = obj->pop("key");
// key, value = dict.popitem() => auto [key, value] = obj->popitem()
auto item = obj->popitem();
// value = dict.setdefault(key, default) => auto value = obj->setdefault(key, default)
auto result = obj->setdefault("new_key", JsonIntCompact::create(100));
// dict1.update(dict2) => obj1->update(*obj2)
obj->update(*other_obj);
// dict.fromkeys(keys, value) => JsonObjectCompact::fromkeys(keys, value)
auto new_obj = JsonObjectCompact::fromkeys({"k1", "k2"}, default_value);
Nested Objects¶
Objects can contain other objects and arrays, allowing for complex nested structures:
auto outer = JsonObjectCompact::create();
auto inner = JsonObjectCompact::create();
auto* inner_obj = std::get<JsonObjectCompact*>(inner.get_mut_ptr());
inner_obj->set("nested_key", JsonIntCompact::create(42));
auto* outer_obj = std::get<JsonObjectCompact*>(outer.get_mut_ptr());
outer_obj->set("inner", inner);
// outer is now {"inner": {"nested_key": 42}}
auto view = outer.get_view();
auto* outer_view = std::get<const JsonObjectCompact*>(view);
auto dump = outer_view->dump(512);
// dump.value() == "{\"inner\": {\"nested_key\": 42}}"
Iterator Support¶
JsonObjectCompact provides bidirectional iterators for traversing key-value pairs:
auto object = JsonObjectCompact::create();
auto* obj = std::get<JsonObjectCompact*>(object.get_mut_ptr());
obj->set("key1", JsonIntCompact::create(1));
obj->set("key2", JsonIntCompact::create(2));
obj->set("key3", JsonIntCompact::create(3));
// Forward iteration
for (auto it = obj->begin(); it != obj->end(); ++it) {
auto pair = *it;
std::string key = std::get<std::string>(pair->first);
JsonHandleCompact value = pair->second;
// Process key-value pair
}
// Backward iteration
auto it = obj->end();
--it; // Move to last element
while (it != obj->begin()) {
auto pair = *it;
// Process key-value pair
--it;
}
Iterator Features:
- Bidirectional: Supports ++ and -- operations
- Insertion Order: Iterates in insertion order
- Value Type: Returns std::pair<KeyType, JsonHandleCompact>
- STL Compatible: Implements std::bidirectional_iterator_tag
Performance Considerations¶
Handle Access (Token → Object)¶
O(1) constant-time access: The handle system uses 32-bit tokens with 30-bit index pinning (bits 29-0). Object access via token is just array indexing:
handles_[token & 0x3FFFFFFF] // Extremely fast, ~2-3 CPU cycles
Thread-safe: Handle manager uses std::recursive_mutex for safe concurrent handle operations.
Memory stable: Indices never change once allocated - freed indices go to a min-heap freelist for reuse.
Key Lookup (String → Value)¶
O(n) linear search through keys array using find() method. Each lookup iterates through all keys comparing strings.
Performance characteristics: - n < 10 keys: Linear search is faster than hash table (cache-friendly, no hash computation) - 10 ≤ n < 50 keys: Comparable performance, linear search may still win due to cache locality - n ≥ 50 keys: Hash table becomes faster (but this library prioritizes memory efficiency)
Optimization strategies:
1. Key ordering: Place frequently-accessed keys at beginning of array
2. Batch operations: Use update() or fromkeys() to reduce multiple lookups
3. External caching: For repeated lookups, cache key indices externally
Insertion Performance¶
New keys: O(n) for set() (calls find() first), O(1) amortized for insert() (no search, direct append)
Existing keys: O(n) for lookup + O(1) for value update
Recommendation: Use insert() when you know the key doesn't exist to skip the O(n) search.
Memory Overhead¶
Per-object overhead:
- 2 handles (keys array + values array): 8 bytes
- Handle manager entry: ~8 bytes (pointer in vector)
- Reference count: 8 bytes (atomic
Comparison with hash tables: - Hash table: ~32-40 bytes per key (load factor 0.75) + collision overhead - This design: ~16 bytes per key (two handles) + no collision overhead - ~40-50% more memory-efficient for small objects (< 100 keys)
Trade-offs¶
This design prioritizes memory efficiency and insertion order preservation over lookup performance.
Optimal use cases: - Small to medium-sized objects (< 50 keys for best performance) - Infrequent lookups or iterator-based access - Memory-constrained environments (embedded systems, mobile) - Scenarios requiring insertion order (JSON serialization, Python dict compatibility) - Many short-lived objects (reduced allocation overhead)
Consider alternatives if: - Frequent key lookups with > 50 keys - Random access dominates over sequential access - Memory is not a constraint
See Also¶
- JsonArrayCompact - JSON array type for sequences
- Handle System - Handle-based memory management
- JsonStructuredCompact - Base class for structured types
- Primitive Types Overview - Immutable primitive types with value deduplication