DEV Community

Cover image for Building Dynamic Yup Validation Schemas from JSON in React + Formik (Part 2)
Shivani R
Shivani R

Posted on

Building Dynamic Yup Validation Schemas from JSON in React + Formik (Part 2)

In the previous article, I showed how I built a dynamic form renderer using JSON configuration in React + Formik.

Rendering the form fields turned out to be the easy part. The real challenge started when I needed validation.

In a traditional form, creating a Yup schema is straightforward because the fields are known in advance.

const validationSchema = yup.object({
    firstName: yup.string().required('First Name is required'),
    email: yup.string().email('Invalid Email'),
});
Enter fullscreen mode Exit fullscreen mode

But in a dynamic form system, fields are generated from configuration. That means validation rules also need to come from configuration.

Hardcoding validation defeats the purpose of having a schema-driven form.

In this article, I'll show how I built dynamic Yup validation schemas directly from JSON configuration.

This is Part 2 of my "Building Dynamic Forms in React" series.


Recap

In Part 1, we built a dynamic form renderer using a schema like this:

{
  field: 'firstName',
  label: 'First Name',
  type: 'text',
  colWidth: 6
}
Enter fullscreen mode Exit fullscreen mode

Now we need to extend the schema to support validation metadata.


Extending the Configuration

I wanted validation to be completely controlled by configuration. So I introduced properties like:

  • isMandatory
  • min
  • max
  • regex

Example:

{
 "field": "firstName",
 "label": "First Name",
 "type": "text",
 "isMandatory": true,
 "min": 3,
 "max": 50
}
Enter fullscreen mode Exit fullscreen mode

For email:

{
 "field": "email",
 "label": "Email",
 "type": "email",
 "isMandatory": true,
 "regex": /^[^\s@]+@[^\s@]+\.[^\s@]+$/
}
Enter fullscreen mode Exit fullscreen mode

Now both the UI and validation rules live in the same configuration.


Why This Matters

Without dynamic validation generation, every new field requires changes in two places:

  1. Form configuration
  2. Validation schema

This quickly becomes difficult to maintain.

The goal is:

Add a field to configuration → validation should automatically work.


Building the Validation Generator

The idea is simple:
Loop through every field and build a Yup schema dynamically.

Something like:

export const buildValidationSchema = (schema) => {
 const validationFields = {};
 Object.values(schema).forEach((fields) => {
  fields.forEach((field) => {
   let validator = Yup.string();
   validationFields[field.field] = validator;
  });
 });

 return Yup.object(validationFields);
};
Enter fullscreen mode Exit fullscreen mode

At this point, every field is a string validator.

Now we can start adding rules.


Handling Required Fields

The first rule I implemented was mandatory field validation.

if (field.isMandatory) {
 validator = validator.required(
  `${field.label} is required`
 );
}
Enter fullscreen mode Exit fullscreen mode

This allows the schema to drive required field validation automatically.

{ field: 'firstName', isMandatory: true }
Enter fullscreen mode Exit fullscreen mode

No additional Yup code required.


Handling Minimum and Maximum Length

Next, I added support for minimum and maximum length validation.

if (field.min) {
 validator = validator.min(field.min, `${field.label} must be at least ${field.min} characters`);
}

if (field.max) {
 validator = validator.max(field.max, `${field.label} must be at most ${field.max} characters`);
}
Enter fullscreen mode Exit fullscreen mode

Configuration:

{ "field": "firstName", "min": 2, "max": 50 }
Enter fullscreen mode Exit fullscreen mode

Generated validation:
Yup.string().min(2).max(50)


Handling Regex Validation

Regex support became useful for:

  • email validation
  • phone numbers
  • custom business rules

Example:

if (field.regex) {
 validator = validator.matches(field.regex, `${field.label} format is invalid`);
}
Enter fullscreen mode Exit fullscreen mode

Configuration:

{ "field": "phone", "regex": /^[0-9]{10}$/ }
Enter fullscreen mode Exit fullscreen mode

Generated validation:
Yup.string().matches(/^[0-9]{10}$/)


Putting Everything Together

The final generator looked something like this:

export const buildValidationSchema = (schema) => {
 const validationFields = {};
 Object.values(schema).forEach((fields) => {
  fields.forEach((field) => {
   let validator = Yup.string();
    if (field.isMandatory) {
     validator = validator.required(`${field.label} is required`);
    }

    if (field.min) {
     validator = validator.min(field.min, `${field.label} must contain at least ${field.min} characters`);
    }

     if (field.max) {
      validator = validator.max(field.max, `${field.label} cannot exceed ${field.max} characters`);
     }

     if (field.regex) {
      validator = validator.matches(field.regex, `${field.label} format is invalid`);
     }

     validationFields[field.field] = validator;
   });
  });

  return Yup.object(validationFields);
};
Enter fullscreen mode Exit fullscreen mode

Now validation automatically adapts whenever configuration changes.


Benefits of This Approach

Single Source of Truth

Validation and rendering stay in the same configuration.

Easier Maintenance

Adding a new field requires only configuration changes.

Scalable Architecture

Works well when forms become:

  • API-driven
  • configurable
  • multi-step
  • enterprise-scale

Reduced Boilerplate

No more manually updating large Yup schemas every time a field changes.


Challenges I Encountered

While building this, I quickly realized validation isn't always this simple.

Real-world forms often need:

  • conditional validation
  • dependent fields
  • dynamic child fields
  • API-driven validation rules

Those scenarios require more advanced schema generation.


What's Next?

So far we've covered:

✅ Part 1: Rendering Dynamic Forms from JSON Configuration
✅ Part 2: Generating Dynamic Yup Validation Schemas

In the next article, I'll cover one of the most interesting challenges I faced:

👉 Handling Conditional Child Fields and Dynamic Validation Dependencies

This is where dynamic forms start becoming much more powerful—and much more complex.

Top comments (1)

Collapse
 
shivani_ravikumar profile image
Shivani R

Hey Folks👋

I'd love to hear how others are handling dynamic validations in their applications. If you're building something similar or would like to see the complete implementation, let me know in the comments 🚀