npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

json2input

v2.0.0

Published

Generate dynamic React inputs from JSON data.

Readme

JSON2Input

JSON2Input is a React component that dynamically converts a JSON object into an editable set of HTML inputs.

The goal of JSON2Input is simple:

Give JSON2Input a JSON object, and let it build the form for you.

Instead of manually creating a form for every property in a JSON structure, JSON2Input recursively walks the data, creates the appropriate inputs, tracks changes, supports nested objects and arrays, and returns the entire updated JSON object.

JSON2Input is being developed with a "make life easier" philosophy. It is intended to handle the repetitive work of creating and maintaining dynamic JSON-backed forms while still keeping the resulting data predictable and accessible to the developer.


Current Status

Version: V1 development

JSON2Input currently supports:

  • Primitive JSON values
  • Nested objects
  • Arrays of primitive values
  • Arrays of objects
  • Nested objects inside arrays
  • Nested arrays
  • Dynamically adding new array items
  • Dynamically adding new objects to arrays
  • Recursive structure detection
  • Path-based updates
  • Retrieving the complete updated JSON object
  • Optional default styling

The project is currently being prepared for publication as an npm package.


Why JSON2Input?

Building a form from a JSON object is usually straightforward until the JSON becomes dynamic.

For example:

const data = {
    name: "BLAH",
    phones: ["000", "000"],
    address: ""
};

A traditional React implementation requires manually creating inputs for:

  • name
  • every item in phones
  • address

That becomes considerably more complicated when the JSON contains nested objects and arrays of objects:

const data = {
    name: "user/delete",
    parameters: [
        {
            name: "email",
            type: "string",
            required: true
        },
        {
            name: "token",
            type: "string",
            required: true
        }
    ],
    conditions: [
        {
            field: "uid",
            operator: "=",
            value: "$email"
        }
    ]
};

JSON2Input handles the recursive rendering for you.


Styling

JSON2Input provides minimal default styling so generated forms are immediately usable, while still giving the consuming application full control over presentation.

By default, JSON2Input applies basic inline styling to generated containers and inputs. If you want to handle all styling yourself, pass true as the second constructor argument:

const form = new JSON2Input(data, true);

This disables JSON2Input's default styling without affecting the generated structure or functionality.

Unique Container IDs

JSON2Input also assigns predictable IDs to generated containers and inputs, making it possible to target specific elements with your own CSS or JavaScript.

Examples include:

json2input-name-single-container
json2input-name-single-input
json2input-phones-array-container
json2input-phones-add-btn
json2input-address-container

Nested objects and arrays also receive dedicated container IDs based on their JSON keys.

This gives developers two options:

// Use JSON2Input's basic styling
const form = new JSON2Input(data);

or:

// Disable default styling and style everything yourself
const form = new JSON2Input(data, true);

The intention is that JSON2Input handles the JSON and form logic, not dictate how your application should look.


Installation

JSON2Input is currently under development and has not yet been published to npm.

Once published, installation will be:

npm install json2input

For development directly from this repository:

git clone <repository-url>
cd <repository-directory>
npm install
npm start

Basic Usage

Import JSON2Input:

import JSON2Input from "./modules/json2input";

Create your JSON data:

const testData = {
    name: "BLAH",
    phones: ["000", "000"],
    address: ""
};

Create the JSON2Input instance:

const form = new JSON2Input(testData);

Render it:

function App() {
    const testData = {
        name: "BLAH",
        phones: ["000", "000"],
        address: ""
    };

    const form = new JSON2Input(testData);

    return (
        <div>
            {form.render()}
        </div>
    );
}

export default App;

JSON2Input will generate inputs corresponding to the JSON structure.


Retrieving Updated Data

JSON2Input maintains the latest form state internally.

Use:

form.getData()

to retrieve the complete updated JSON object.

For example:

<button
    type="button"
    onClick={() => {
        console.log(form.getData());
    }}
>
    Get Data
</button>

If the original data is:

const data = {
    name: "BLAH",
    phones: ["000", "000"],
    address: ""
};

and the user changes the name to:

John

and the first phone number to:

555-1234

then:

form.getData();

returns:

{
    name: "John",
    phones: ["555-1234", "000"],
    address: ""
}

JSON2Input returns the entire JSON object, not just the value that changed.


How JSON2Input Works

JSON2Input recursively walks the supplied JSON object.

At a high level:

JSON
 |
 +-- primitive
 |     |
 |     +-- text input
 |
 +-- object
 |     |
 |     +-- recursively render its properties
 |
 +-- array
       |
       +-- inspect its items
       |
       +-- render each item
       |
       +-- provide + Add

The renderer determines whether each value is:

Array.isArray(value)

an object:

typeof value === "object" && value !== null

or a primitive value.

This allows the same renderer to work with JSON structures of different shapes.


Paths

One of the most important concepts in JSON2Input is the path.

A path represents the exact location of a value inside the JSON object.

For example:

{
    address: {
        city: "Austin"
    }
}

The path to city is:

["address", "city"]

For arrays, indexes are included in the path.

For example:

{
    phones: [
        "111",
        "222"
    ]
}

The paths are:

["phones", 0]
["phones", 1]

A more complex example:

{
    routes: [
        {
            parameters: [
                {
                    name: "email"
                }
            ]
        }
    ]
}

The path to name is:

["routes", 0, "parameters", 0, "name"]

Paths allow JSON2Input to update the exact value that the user changed without needing to know anything about the specific JSON structure.


Updating Values

When an input changes, JSON2Input receives:

path + new value

For example:

path = ["routes", 0, "parameters", 0, "name"];
value = "username";

JSON2Input follows the path through the current JSON data and updates the appropriate property.

Conceptually:

formData
   |
   +-- routes
        |
        +-- [0]
             |
             +-- parameters
                  |
                  +-- [0]
                       |
                       +-- name

The resulting JSON is then stored as the latest form state.


Arrays

Arrays receive special handling.

For example:

const data = {
    names: ["John", "Hammond"]
};

JSON2Input renders:

Names

[ John     ]
[ Hammond  ]

[ + Add ]

Clicking + Add creates another input:

Names

[ John     ]
[ Hammond  ]
[          ]

[ + Add ]

The resulting JSON becomes:

{
    names: [
        "John",
        "Hammond",
        ""
    ]
}

Arrays of Objects

This is where JSON2Input becomes particularly useful.

Consider:

const data = {
    conditions: [
        {
            field: "uid",
            operator: "=",
            value: "$email"
        }
    ]
};

The array does not contain simple text values. It contains objects.

JSON2Input recognizes this and renders the object's properties instead of attempting to place the entire object into a text input.

The structure is effectively:

Conditions

Field
[ uid ]

Operator
[ = ]

Value
[ $email ]

[ + Add ]

When another condition is added, JSON2Input creates a new object with the same structure:

{
    field: "",
    operator: "",
    value: ""
}

The resulting JSON becomes:

{
    conditions: [
        {
            field: "uid",
            operator: "=",
            value: "$email"
        },
        {
            field: "",
            operator: "",
            value: ""
        }
    ]
}

How Dynamic Object Creation Works

JSON2Input does not need to know what an object represents.

It does not need special logic such as:

if (key === "routes") {
    ...
}

Instead, when an item is added to an array, JSON2Input looks at the existing structure.

If an array already contains an item, the previous item can be used as the structural template for the new item.

For example:

routes[4]

exists.

The user clicks + Add, so JSON2Input creates:

routes[5]

using the structure of:

routes[4]

The values are cleared while the structure is preserved.

For example:

{
    name: "user/delete",
    parameters: [
        {
            name: "email",
            type: "string"
        }
    ]
}

becomes:

{
    name: "",
    parameters: [
        {
            name: "",
            type: ""
        }
    ]
}

This allows deeply nested structures to remain intact when new items are added.


Nested Arrays

JSON2Input also handles arrays nested inside other structures.

For example:

{
    groups: [
        {
            name: "Administrators",
            members: [
                "John",
                "Jane"
            ]
        }
    ]
}

Paths allow the renderer to distinguish between:

["groups", 0, "name"]

and:

["groups", 0, "members", 0]

The same recursive rendering and update system is used regardless of how deeply the data is nested.


Empty Arrays

There is an unavoidable ambiguity with an empty array.

For example:

{
    something: []
}

The JSON itself does not tell us whether the array is intended to contain:

["one", "two"]

or:

[
    {
        name: "John"
    }
]

For V1, JSON2Input uses a simple rule:

If there is no existing item from which to determine the structure, assume the new item is a text value.

Therefore:

{
    something: []
}

followed by + Add becomes:

{
    something: [""]
}

This behavior may evolve in a future version as more explicit schema support is introduced.


Template Tracking

When JSON2Input encounters an object containing an array, it remembers the structure that belongs inside that array.

For example:

{
    parameters: [
        {
            name: "email",
            type: "string",
            required: true
        }
    ]
}

JSON2Input can remember that:

parameters
    |
    +-- array
          |
          +-- object
                |
                +-- name
                +-- type
                +-- required

This becomes important when a new parent object is added.

For example, when a new route is created:

routes[5]

its nested:

parameters

array can still retain knowledge that its items are objects.

This allows the user to subsequently click:

Parameters
+ Add

and receive the correct object fields rather than a single [object Object] text input.


Default Styling

JSON2Input includes basic default styling to make the generated form usable immediately.

By default:

const form = new JSON2Input(data);

will apply basic inline styles to generated elements.

To disable the default styling:

const form = new JSON2Input(
    data,
    true
);

The second constructor argument is:

disableDefaultStyling

Example:

const form = new JSON2Input(
    testData,
    true
);

This allows the application using JSON2Input to completely control the styling.


Constructor

new JSON2Input(data, disableDefaultStyling)

data

The JSON object that should be converted into inputs.

Example:

const data = {
    name: "John",
    phones: ["111", "222"]
};

disableDefaultStyling

Optional boolean.

Default:

false

Set to true to prevent JSON2Input from applying its built-in inline styles.


Methods

render()

Renders the JSON data as React elements.

Example:

{form.render()}

getData()

Returns the latest complete JSON object represented by the form.

Example:

const data = form.getData();

console.log(data);

The returned object represents the entire current form state.


React State

Internally, JSON2Input maintains the current form data using React state.

Conceptually:

Initial JSON
     |
     v
React state
     |
     v
Rendered inputs
     |
     v
User changes input
     |
     v
Path + new value
     |
     v
Updated JSON
     |
     v
React state

The latest state is exposed through:

form.getData()

This keeps the implementation simple for applications that primarily want JSON2Input to handle the form state automatically.


Testing

The project uses:

  • Jest
  • React Testing Library
  • @testing-library/user-event

Run the test suite with:

npm test

Tests currently live under:

src/tests/

The test suite is intended to verify behavior from the user's perspective, particularly:

  • Inputs render from JSON
  • Input changes update the correct JSON value
  • Array values update correctly
  • Objects inside arrays are rendered correctly
  • New array items are created correctly
  • Nested structures retain their expected shape
  • getData() returns the expected complete JSON object

Example Project Structure

A development project currently follows this general structure:

se_json2input/
|
├── public/
|
├── src/
│   ├── data/
│   │   └── config.json
│   │
│   ├── modules/
│   │   └── json2input.js
│   │
│   ├── tests/
│   │   └── json2input.test.js
│   │
│   ├── App.jsx
│   ├── App.css
│   ├── index.css
│   └── index.js
│
├── package.json
└── README.md

Example: Complex JSON

JSON2Input is designed to work with structures such as:

const config = {
    database: {
        host: "localhost",
        port: 5432,
        user: "oneapi",
        password: "securepassword",
        name: "mydatabase"
    },

    routes: [
        {
            name: "user/get",
            action: "getByField",
            table: "user",
            auth_required: false,
            parameters: [
                {
                    name: "email",
                    type: "string",
                    required: true
                }
            ]
        },

        {
            name: "user/delete",
            action: "deleteByConditions",
            table: "user",
            auth_required: true,
            parameters: [
                {
                    name: "email",
                    type: "string",
                    required: true,
                    table_field: "uid"
                }
            ],
            conditions: [
                {
                    field: "uid",
                    operator: "=",
                    value: "$email"
                }
            ]
        }
    ]
};

The important point is that JSON2Input does not need to know what a database, route, parameter, or condition is.

It only needs to understand the JSON structure.


Design Philosophy

JSON2Input is intentionally designed around a few principles.

1. JSON is the source of structure

The component should not require developers to manually define every input.

The JSON structure determines what gets rendered.

2. Paths identify data

Every input has a path back to its location in the JSON.

This allows updates to remain generic and independent of the actual property names.

3. Recursive rendering

Objects and arrays can contain other objects and arrays.

The renderer therefore needs to recursively process the data instead of making assumptions about its depth.

4. Add operations preserve structure

When the user adds an item to an array, JSON2Input attempts to determine what that item should look like based on existing data and remembered templates.

5. Keep application code simple

The application should primarily need to do this:

const form = new JSON2Input(data);

and later:

const updatedData = form.getData();

The repetitive form-management work should happen inside JSON2Input.


Current Limitations

JSON2Input is currently a V1 implementation.

Known limitations include:

Input types

At the moment, generated values are primarily rendered as:

<input type="text">

This means values such as:

true
false
123

may currently be represented as strings after user interaction.

Future versions may infer and support appropriate input types such as:

  • text
  • number
  • checkbox
  • date
  • select

and potentially allow custom input rendering.

Empty arrays

An empty array does not contain enough information to determine its intended item type.

V1 therefore assumes a text value unless structural information has previously been recorded.

JSON-compatible data

The current implementation is designed around JSON-compatible values.

The cloning strategy currently uses:

JSON.parse(JSON.stringify(value))

so JavaScript-specific values such as functions, class instances, Date objects, Map, and Set are outside the intended data model.

Styling

Default styling is intentionally minimal.

The styling system is expected to become more flexible as the package develops.


Roadmap

The project is currently focused on getting a solid V1 implementation published and usable.

Potential future improvements include:

  • [ ] Publish to npm
  • [ ] Publish the project to GitHub
  • [ ] Add package documentation
  • [ ] Expand automated test coverage
  • [ ] Better boolean handling
  • [ ] Automatic number/type detection
  • [ ] Support for custom input types
  • [ ] Custom renderers
  • [ ] Custom styling
  • [ ] Remove array items
  • [ ] Reorder array items
  • [ ] Better handling of empty arrays
  • [ ] More sophisticated schema support
  • [ ] TypeScript support
  • [ ] Production build/package configuration
  • [ ] More comprehensive examples
  • [ ] CI/CD testing

Development

Install dependencies:

npm install

Start the development application:

npm start

Run tests:

npm test

Create a production build:

npm run build

Contributing

JSON2Input is being developed as an open-source project.

Contributions, bug reports, feature requests, and suggestions are welcome.

When contributing, please consider whether a proposed change keeps the component generic.

For example, adding logic specifically for:

routes

would make JSON2Input less reusable.

Prefer logic based on:

value type
path
array structure
object structure

rather than specific application property names.


License

License information will be added before the first public npm release.


Project Goal

JSON2Input exists to make one particular problem easier:

Turning arbitrary JSON structures into usable React forms without manually building every input.

The long-term goal is to make JSON2Input flexible enough to handle complex real-world JSON while keeping the developer-facing API extremely simple.

Ideally, the common case should remain:

const form = new JSON2Input(data);

Render it:

{form.render()}

Then retrieve the user's changes:

const updatedData = form.getData();

The complexity should live inside JSON2Input — not inside the application using it.