pub struct Entity {
pub count: Option<Count>,
pub seed: Option<u64>,
pub unique_by: Vec<String>,
pub fields: IndexMap<String, Field>,
}Expand description
Represents an entity specification for generating structured data objects in JGD schemas.
Entity defines a collection of named fields that together form a structured data object.
It supports generating single objects or arrays of objects, with optional uniqueness
constraints to ensure no duplicate entities based on specified field combinations.
§JGD Schema Integration
Entities are the primary building blocks for creating structured data in JGD schemas. They correspond to objects in JSON and can contain multiple fields of different types, creating realistic data structures for testing and development.
§Features
- Multiple Fields: Define complex objects with various field types
- Count Control: Generate single objects or arrays of objects
- Uniqueness Constraints: Ensure entities are unique based on specified fields
- Seeding Support: Optional seed for deterministic generation
- Cross-References: Fields can reference other generated entities
§JSON Schema Representation
{
"entity": {
"count": 10,
"unique_by": ["id", "email"],
"fields": {
"id": "${uuid}",
"name": "${name.fullName}",
"email": "${internet.email}",
"age": {
"number": {
"min": 18,
"max": 65,
"integer": true
}
}
}
}
}§Uniqueness Constraints
The unique_by field allows specifying which field combinations must be unique
across all generated entities. This is useful for:
- Primary key constraints (IDs, usernames, emails)
- Composite uniqueness (user + project combinations)
- Realistic data constraints (no duplicate SSNs, etc.)
§Examples
use jgd_rs::{Entity, Field, Count, JsonGenerator, GeneratorConfig};
use indexmap::IndexMap;
let mut config = GeneratorConfig::new("EN", Some(42));
// Create user entities with unique emails
let mut fields = IndexMap::new();
fields.insert("id".to_string(), Field::Str("${uuid}".to_string()));
fields.insert("name".to_string(), Field::Str("${name.fullName}".to_string()));
fields.insert("email".to_string(), Field::Str("${internet.email}".to_string()));
let entity = Entity {
count: Some(Count::Fixed(5)),
seed: None,
unique_by: vec!["email".to_string()],
fields,
};
let result = entity.generate(&mut config);
// Generates an array of 5 user objects with unique emailsFields§
§count: Option<Count>Optional count specification for the number of entities to generate.
Determines whether to generate a single entity object or an array of entities:
- Some(count): Generates an array with the specified count
- None: Generates a single entity object (not wrapped in an array)
This field works with the GetCount trait to provide flexible count specifications
including fixed counts and ranges.
§JSON Schema Mapping
{
"entity": {
"count": 5, // Generate 5 entities
"fields": { ... }
}
}Or omitted for single entity:
{
"entity": {
"fields": { ... } // Generate single entity
}
}seed: Option<u64>Optional seed for deterministic entity generation.
When specified, this seed can be used to ensure reproducible entity generation for testing and debugging purposes. Currently preserved for future implementation of per-entity seeding.
§Future Enhancement
This field is planned for use in scenarios where specific entities need their own deterministic generation context, separate from the global generator configuration seed.
§JSON Schema Mapping
{
"entity": {
"seed": 12345,
"fields": { ... }
}
}unique_by: Vec<String>Fields that must be unique across all generated entities.
This vector specifies which field combinations must be unique when generating multiple entities. The uniqueness check creates a fingerprint from the specified fields and ensures no duplicates are generated.
§Uniqueness Behavior
- Empty vector: No uniqueness constraints (default)
- Single field: Ensures that field is unique across entities
- Multiple fields: Ensures the combination of fields is unique
§Performance Considerations
Uniqueness checking has a maximum retry limit (1000 attempts) to prevent infinite loops when constraints are too restrictive relative to the possible value space.
§JSON Schema Mapping
{
"entity": {
"unique_by": ["id"], // Single field uniqueness
"fields": { ... }
}
}Or multiple fields:
{
"entity": {
"unique_by": ["user_id", "project_id"], // Composite uniqueness
"fields": { ... }
}
}§Examples
// Ensure email uniqueness
unique_by: vec!["email".to_string()]
// Ensure user+project combination uniqueness
unique_by: vec!["user_id".to_string(), "project_id".to_string()]fields: IndexMap<String, Field>The collection of fields that make up the entity structure.
This IndexMap defines the schema for the generated entities, mapping field
names to their generation specifications. The use of IndexMap preserves
the field ordering defined in the schema.
§Field Types
Each field can be any valid Field type:
- Primitive fields: Strings, numbers, booleans
- Complex fields: Nested entities, arrays
- Template fields: String templates with placeholder substitution
- Reference fields: Cross-references to other generated data
- Optional fields: Fields that may or may not be present
§Field Independence
Each field is generated independently, allowing for:
- Different fake data for each field
- Independent randomization
- Cross-field references when needed
§JSON Schema Mapping
{
"entity": {
"fields": {
"id": "${uuid}",
"name": "${name.fullName}",
"age": {
"number": {
"min": 18,
"max": 65,
"integer": true
}
},
"address": {
"entity": {
"fields": {
"street": "${address.streetAddress}",
"city": "${address.cityName}"
}
}
}
}
}
}Trait Implementations§
Source§impl<'de> Deserialize<'de> for Entity
impl<'de> Deserialize<'de> for Entity
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl JsonGenerator for Entity
impl JsonGenerator for Entity
Source§fn generate(
&self,
config: &mut GeneratorConfig,
local_config: Option<&mut LocalConfig>,
) -> Result<Value, JgdGeneratorError>
fn generate( &self, config: &mut GeneratorConfig, local_config: Option<&mut LocalConfig>, ) -> Result<Value, JgdGeneratorError>
Generates entities according to the entity specification with uniqueness constraints.
This method creates either a single entity object or an array of entities, depending on the count specification. When uniqueness constraints are specified, it ensures that no duplicate entities are generated based on the unique field combinations.
§Generation Process
- Count Determination: Uses count specification to determine output format
- Uniqueness Setup: Initializes tracking for unique field combinations
- Entity Generation: Creates entities with uniqueness validation
- Output Formation: Returns single object or array based on count
§Arguments
config- Mutable reference to the generator configuration containing RNG, fake data generators, and cross-reference state
§Returns
- Single Entity:
Value::Objectwhen count is None - Entity Array:
Value::Arraywhen count is specified
§Uniqueness Algorithm
When unique_by fields are specified:
- Generate a candidate entity
- Create a fingerprint from the unique fields
- Check if fingerprint already exists
- If unique, add to results; if duplicate, retry
- Maximum 1000 attempts per entity to prevent infinite loops
§Error Handling
- Uniqueness Failures: Logs warning and stops generation after max attempts
- Missing Fields: Includes “missing” in fingerprint for absent unique fields
- Complex Values: Serializes complex field values for fingerprinting
§Examples
use jgd_rs::{Entity, Field, Count, JsonGenerator, GeneratorConfig};
use indexmap::IndexMap;
let mut config = GeneratorConfig::new("EN", Some(42));
// Single entity generation
let mut fields = IndexMap::new();
fields.insert("name".to_string(), Field::Str("${name.fullName}".to_string()));
fields.insert("age".to_string(), Field::I64(25));
let entity = Entity {
count: None, // Single entity
seed: None,
unique_by: vec![],
fields,
};
let result = entity.generate(&mut config);
// Returns: {"name": "John Doe", "age": 25}
// Array of unique entities
let entity_array = Entity {
count: Some(Count::Fixed(3)),
unique_by: vec!["name".to_string()],
fields: fields.clone(),
};
let result = entity_array.generate(&mut config);
// Returns: [{"name": "John", "age": 25}, {"name": "Jane", "age": 25}, ...]§Performance Notes
- Memory Efficiency: Pre-allocates result vector with known capacity
- Uniqueness Overhead: Fingerprinting and set operations add computational cost
- Retry Limits: Maximum attempts prevent infinite loops in constrained scenarios
- Fingerprint Storage: Memory usage grows with unique entity count
§Uniqueness Constraints
Consider the value space when setting uniqueness constraints:
- Large Value Space: Easy to generate unique entities
- Small Value Space: May hit retry limits with restrictive constraints
- Template Variety: Ensure fake data templates provide sufficient variation
Auto Trait Implementations§
impl Freeze for Entity
impl RefUnwindSafe for Entity
impl Send for Entity
impl Sync for Entity
impl Unpin for Entity
impl UnsafeUnpin for Entity
impl UnwindSafe for Entity
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more