JSON Mock Data Generator: Field Type System and Random Data Algorithms#

A deep dive into implementing a flexible JSON mock data generator, covering field type systems, random data generation algorithms, and batch generation optimization.

In modern frontend development with API-first architecture, mock data is essential. Today we’ll explore how to build a flexible JSON mock data generator—not just random strings, but intelligent test data that matches field semantics.

Core Data Structure Design#

The heart of a mock data generator is the field configuration. We need a flexible type system to describe each field:

type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'email' | 'name' | 'phone' | 'id' | 'array' | 'object'

interface Field {
  name: string      // Field name
  type: FieldType   // Field type
}

// Example configuration
const fields: Field[] = [
  { name: 'id', type: 'id' },
  { name: 'name', type: 'name' },
  { name: 'email', type: 'email' },
  { name: 'age', type: 'number' },
  { name: 'createdAt', type: 'date' },
]

The type system has three categories:

  • Basic types: string, number, boolean, date
  • Semantic types: email, name, phone, id (with specific format requirements)
  • Composite types: array, object (nested structures)

Random Data Generation Algorithms#

Each type needs a corresponding generator function. The key is making data look “realistic”—not completely random, but matching business scenarios.

1. Semantic Type Generators#

Name generation is a classic random combination problem:

const firstNames = ['John', 'Jane', 'Mike', 'Emily', 'David', 'Sarah', 'Chris', 'Emma']
const lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis']

function generateName(): string {
  const first = firstNames[Math.floor(Math.random() * firstNames.length)]
  const last = lastNames[Math.floor(Math.random() * lastNames.length)]
  return `${first} ${last}`
}

Two important considerations:

  1. Name pools should cover common names for your target audience
  2. Avoid generating awkward combinations (cultural sensitivity matters)

2. Email Generation Algorithm#

Emails follow a predictable pattern:

function generateEmail(index: number): string {
  return `user${index + 1}@example.com`
}

This guarantees uniqueness through the index parameter. For more realistic emails:

function generateRealisticEmail(name: string): string {
  const domains = ['gmail.com', 'yahoo.com', 'outlook.com', 'company.com']
  const domain = domains[Math.floor(Math.random() * domains.length)]
  const cleanName = name.toLowerCase().replace(/\s+/g, '.')
  return `${cleanName}@${domain}`
}

3. Date Generation Strategy#

Generate random dates from the past to simulate business data:

function generateDate(): string {
  const date = new Date()
  // Randomly go back 0-365 days
  date.setDate(date.getDate() - Math.floor(Math.random() * 365))
  return date.toISOString().split('T')[0] // YYYY-MM-DD
}

For future dates (like appointment times), simply use addition instead.

4. Auto-increment ID Implementation#

ID fields need uniqueness. The simplest approach uses loop index:

function generateId(index: number): number {
  return index + 1 // Start from 1
}

Pass the index during batch generation:

for (let i = 0; i < count; i++) {
  const item: Record<string, any> = {}
  fields.forEach(field => {
    item[field.name] = generateValue(field.type, i) // Pass index
  })
  data.push(item)
}

Performance Optimization: Batch Generation Pitfalls#

Generating 100 records is instant. But for 10,000+ records, there are traps:

Pitfall 1: String Concatenation#

Wrong approach (creates new string each iteration):

let json = '['
for (let i = 0; i < 10000; i++) {
  json += JSON.stringify(item) + ','
}
json = json.slice(0, -1) + ']'

Correct approach (array join):

const data = []
for (let i = 0; i < 10000; i++) {
  data.push(item)
}
const json = JSON.stringify(data)

Pitfall 2: Frequent Re-renders#

In React, modifying fields triggers component re-renders. Optimize with:

const generateMock = useCallback(() => {
  // Store in local variable, setState once at the end
  const data = []
  for (let i = 0; i < count; i++) {
    data.push(generateItem(fields, i))
  }
  setOutput(JSON.stringify(data, null, 2))
}, [fields, count])

Extension: Supporting Nested Structures#

The current implementation handles array and object types with hardcoded values:

case 'array':
  return [1, 2, 3] // Simplified
case 'object':
  return { key: 'value' }

Full implementation needs recursive configuration:

interface Field {
  name: string
  type: FieldType
  children?: Field[]    // Nested fields
  itemType?: FieldType  // Array element type
}

Now you can generate complex structures:

{
  "id": 1,
  "profile": {
    "name": "John Smith",
    "age": 28
  },
  "tags": ["vip", "active", "premium"]
}

Real-World Use Cases#

Mock data generators are invaluable in frontend development:

  1. API Debugging: Develop frontend while backend APIs are still in progress
  2. Performance Testing: Generate large datasets to test list rendering performance
  3. Edge Case Testing: Generate super-long strings, special characters, boundary conditions
  4. Demo Presentations: Quickly generate sample data without manual entry

JsonKit’s JSON Mock Data Generator supports 10 field types with configurable generation count, perfect for rapid frontend development. Try it at https://jsokit.com/tools/json-mock.