What this tool does
A JSON sample becomes a Mongoose schema, one const per object, and a model at the end.
{ "id": 1, "name": "Ada", "address": { "city": "Paris" } }
import mongoose from 'mongoose';
const AddressSchema = new mongoose.Schema({
city: { type: String, required: true },
});
const RootSchema = new mongoose.Schema({
id: { type: Number, required: true },
name: { type: String, required: true },
address: { type: AddressSchema, required: true },
});
export default mongoose.model('Root', RootSchema);
Children first: schemas are runtime values, so one has to exist before another uses it. An array of documents at the root describes its first element — that is the shape of the record, and the list is what the collection already is.
required on an array needs help
Mongoose gives every array a default of []. A field declared { type: [String], required: true } therefore validates even when the key is absent: the default satisfies the requirement. Checked on Mongoose 9:
| document | required: true | required: true, default: undefined |
|---|---|---|
{ tags: ["a"] } | passes | passes |
{ tags: [] } | passes | passes |
{} | passes | fails |
The first column is not what the word says. Array fields are therefore emitted with default: undefined alongside required: true, so a missing array is the error it claims to be. An empty array still passes, which is right: it is a value.
Nested objects become subdocuments, with their own _id
address above is a subdocument, and Mongoose gives it an _id of its own:
{ _id: ObjectId("…"), address: { city: "Paris", _id: ObjectId("…") } }
That is Mongoose’s default, not something added here. If those inner identifiers are noise for you, new mongoose.Schema({ … }, { _id: false }) removes them — a decision about your documents, which is why it is left to you.
A MongoDB export is not the JSON you want
mongoexport writes extended JSON:
{ "_id": { "$oid": "65f1c…" }, "created": { "$date": "2026-01-01T00:00:00Z" } }
Those are objects, so the generator makes subdocument schemas of them — _id ends up as a subdocument that carries its own _id, which is certainly not what you meant. Replace them with mongoose.Schema.Types.ObjectId and Date by hand. A key named $oid means something to MongoDB and nothing to a structural reader.
Mixed is where the sample went quiet
null, an unknown value, an empty array and a heterogeneous array all give mongoose.Schema.Types.Mixed. A Mixed field is not validated and, worth knowing, changes to it are not tracked automatically — you have to call markModified. Narrow it as soon as you know what belongs there.
Private by design
Everything runs locally in your browser with JavaScript. Your data is never uploaded, which makes the tool safe for sensitive content, and it keeps working offline.