Object Iterators
Relevant source files
The following files were used as context for generating this wiki page:
Object Iterators in libfastjson provide a structured and abstracted method for traversing the name/value pairs within a JSON Object. This API is designed to hide the internal implementation details of how the library stores key-value pairs, ensuring that client code remains decoupled from the private data structures of the library.
The iterator system follows a standard "begin/end" pattern common in many collection libraries, allowing for safe traversal from the first element to the position just beyond the last element. It is specifically designed for objects of type fjson_type_object and handles internal paging mechanisms automatically.
Sources: json_object_iterator.h:20-40, json_object_iterator.c:23-40
Architecture and Data Structures
The iterator architecture is built around a specific structure that tracks the progress of traversal through internal linked pages of children.
The fjson_object_iterator Structure
The iterator itself is an opaque structure containing the necessary state to maintain the current position during iteration.
struct fjson_object_iterator {
int objs_remain;
int curr_idx;
const struct _fjson_child_pg *pg;
};
Sources: json_object_iterator.h:47-51
| Field | Description |
|---|---|
objs_remain | The number of objects left to be visited in the current iteration. |
curr_idx | The current index within the specific page of children. |
pg | A pointer to the current internal page (_fjson_child_pg) being traversed. |
Sources: json_object_iterator.h:48-50, json_object_iterator.c:65-72
Object Internal Layout
Internal storage for objects uses a paged approach defined by FJSON_OBJECT_CHLD_PG_SIZE (defaulting to 8). The iterator must navigate these pages and skip empty slots (where the key k is NULL) to present a continuous stream of valid pairs to the user.
Sources: json_object.h:47-51, json_object_iterator.c:75-80
Iteration Logic and Flow
The following diagram illustrates the lifecycle of an iteration process, from initialization to completion.
The iteration flow ensures that even if an object is empty, the "begin" iterator will immediately match the "end" iterator.
Sources: json_object_iterator.c:64-105, json_object_iterator.h:74-90
Core Iterator API Functions
The API provides several functions to manage the iterator state and access data.
| Function | Purpose |
|---|---|
fjson_object_iter_begin() | Retrieves an iterator pointing to the first name/value pair. |
fjson_object_iter_end() | Retrieves an iterator representing the position beyond the last pair. |
fjson_object_iter_next() | Advances the iterator to the next valid pair, skipping empty slots. |
fjson_object_iter_peek_name() | Returns a const char* to the key of the current pair. |
fjson_object_iter_peek_value() | Returns the fjson_object* value of the current pair. |
fjson_object_iter_equal() | Compares two iterators (typically used for the loop condition). |
Sources: json_object_iterator.h:60-220, json_object_iterator.c:64-180
Implementation Details
Advancement Logic
When fjson_object_iter_next is called, the library decrements the remaining object count. If the curr_idx reaches the page size limit, the iterator automatically moves to the next page in the linked list. It also includes recursive logic to skip internal slots that have been deleted or are otherwise empty.
Sources: json_object_iterator.c:100-118
Serialization Integration
The iteration system is heavily utilized by the library's serialization logic. For example, in json_print.c, the write_object function uses the iterator to traverse and format the JSON string.
struct fjson_object_iterator it = fjson_object_iter_begin(jso);
struct fjson_object_iterator itEnd = fjson_object_iter_end(jso);
while (!fjson_object_iter_equal(&it, &itEnd)) {
// ... write key/value pairs ...
fjson_object_iter_next(&it);
}
Sources: json_print.c:367-386
Usage and Safety Guidelines
- Invalidation: Any modification to the underlying object (such as
fjson_object_object_del) invalidates existing iterators. If a deletion is required during a loop, the iterator must be advanced before the deletion occurs. - Thread Safety: The iterator API is neither thread-safe nor reentrant.
- Null Values: In
libfastjson, a JSONnullvalue is represented by aNULLpointer returned byfjson_object_iter_peek_value. - End Iterators: Users should not assume the internal value of the "end" iterator (e.g., that it is
NULL). Always usefjson_object_iter_equalfor comparisons.
Sources: json_object_iterator.h:25-35, 80-85, 175-185, tests/testReplaceExisting.c:45-55
Summary
Object Iterators provide the primary mechanism for developers to interact with JSON objects as collections in libfastjson. By abstracting the paged internal storage into a standard iterator interface, the library maintains performance for large objects while providing a clean API for traversal used in both internal printing functions and external client applications.