Box<T> for Recursive JSON Structures
Use Box<T> to break infinite-size recursion when a struct refers to itself, like a tree node or a linked list of comments.
Detailed Explanation
Box for Self-Referential Structs
Rust needs to know a struct's exact size at compile time. A struct that contains itself directly would have infinite size, so the compiler refuses. Box<T> puts the inner value on the heap, so the parent only stores a pointer-sized field.
Example JSON (a comment thread)
{
"id": 1,
"text": "Top-level comment",
"replies": [
{
"id": 2,
"text": "First reply",
"replies": [
{ "id": 3, "text": "Nested reply", "replies": [] }
]
}
]
}
Auto-generated output (before refactor)
The converter cannot detect that replies is the same shape as the parent. It generates separate structs (Comment, CommentReplies, etc.) that quickly diverge from your intent.
Hand-edited recursive struct
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Comment {
pub id: i64,
pub text: String,
pub replies: Vec<Comment>,
}
This compiles because Vec<Comment> stores its elements on the heap — the recursion is broken by the indirection Vec provides internally.
When you actually need Box
If the recursive field is a single optional child rather than a vector, you need Box<T> explicitly:
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Node {
pub value: i64,
pub next: Option<Box<Node>>,
}
Without Box, the compiler emits "recursive type Node has infinite size".
Trees with multiple children
pub struct Tree {
pub value: i64,
pub left: Option<Box<Tree>>,
pub right: Option<Box<Tree>>,
}
Each Box is a single pointer (8 bytes on 64-bit systems), so the tree is compact regardless of depth.
Cost of Box
Each Box<T> is one heap allocation per node. For thousands of nodes this is fine; for millions, consider an arena allocator like bumpalo or store nodes in a flat Vec indexed by usize.
Use Case
Comment threads, file system trees, AST nodes, organizational hierarchies, and reply chains in messaging apps all need recursive types. Box<T> and Vec<T> are the two tools that make them work in Rust.