<p>You can write a simple <a href="https://craftcms.com/docs/4.x/extend/migrations.html" rel="nofollow noreferrer">migration</a> that uses Craft's API to create entries programmatically. You can generate a new migration with the <a href="https://craftcms.com/docs/4.x/console-commands.html#migrate-create" rel="nofollow noreferrer"><code>migrate/create</code> console command</a>:</p>
<pre class="lang-bash prettyprint-override"><code>php craft migrate/create content_import
</code></pre>
<p>This will create a new PHP file in the <code>migrations/</code> folder. You can put the migration code inside the <code>safeUp</code> method. To execute the migration:</p>
<pre class="lang-bash prettyprint-override"><code>php craft migrate/up
</code></pre>
<p>Inside the migration, you need access to your JSON. You can put the entire JSON string inside the migration, but I usually don't want to have that much data in my source control. Instead, I like to put the JSON inside the <code>migrations/</code> folder and load it inside the <code>safeUp</code> method:</p>
<pre class="lang-php prettyprint-override"><code>$json = file_get_contents(__DIR__ . 'data.json');
$rows = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
</code></pre>
<p>This means you need to place this file in the production server manually, but that's fine since it's a one-time operation.</p>
<p>Once the JSON is loaded, you can create entries through the <a href="https://docs.craftcms.com/api/v3/craft-services-elements.html#method-saveelement" rel="nofollow noreferrer"><code>Elements</code> service</a>:</p>
<pre class="lang-php prettyprint-override"><code>$contentSection = \Craft::$app-&gt;sections-&gt;getSectionByHandle('myContentSection');
$contentEntryType = $contentSection-&gt;getEntryTypes()[0];

foreach ($rows as $row) {
    $entry = new \craft\elements\Entry();
    $entry-&gt;sectionId = $contentSection-&gt;Id;
    $entry-&gt;typeId = $contentEntryType-&gt;id;
    $entry-&gt;enabled = true;
    $entry-&gt;title = $row['title'];
    // Set more properties as needed, i.e. slug, postDate, etc.

    $entry-&gt;setFieldValues([
        'body' =&gt; $row['body'],
        // Set other custom fields
    ]);

    $success = \Craft::$app-&gt;elements-&gt;saveElement($entry);
    if (!$success) {
        \Craft::error('Couldn’t save the entry &quot;' . $entry-&gt;title . '&quot;', __METHOD__);
        return false;
    }
}
</code></pre>
<p>To test the migration repeatedly during migration, you need to modify the <code>safeDown</code> method. I like to put in code that deletes all the imported entries (careful, the following will delete all entries in the given section):</p>
<pre class="lang-php prettyprint-override"><code>$content = \craft\elements\Entry::find()
    -&gt;section('myContentSection')
    -&gt;status(null)
    -&gt;all();

foreach ($content as $entry) {
    \Craft::$app-&gt;elements-&gt;deleteElement($entry, true);
}
</code></pre>
<p>Then you can redo the migration for testing purposes like this:</p>
<pre class="lang-bash prettyprint-override"><code>php craft migrate/redo 1
</code></pre>
<hr />
<p>This may look complicated, but is pretty simple and quick once you've done it a few times. If this seems daunting, Feed Me is probably the better option.</p>

CC BY-SA 4.0
2023-07-31T15:34:53.543Z
2023-07-31T15:34:53.543Z
MoritzLost
<p>Personally, I'd use FeedMe. It's excellent. If you don't need it again just remove it after you have used it.</p>

CC BY-SA 4.0
2023-08-04T13:24:33.830Z
2023-08-04T13:24:33.830Z
Seth Warburton
<p>I have some entries saved in a JSON file with the standard format that is created with export functionality (expanded). How can I import the entries from this JSON file back to my CMS?</p>
<p>Feed Me seems to be a complex streamline solution, but all I need is a single-time import.
Craftimport only allows XML and seems outdated and unmaitained.</p>

<entries><import><export>
How to manually import entries into Craft CMS?
# How to manually import entries into Craft CMS?

(Asked by: username_0 on 2023-07-31)

I have some entries saved in a JSON file with the standard format that is created with export functionality (expanded). How can I import the entries from this JSON file back to my CMS?

Feed Me seems to be a complex streamline solution, but all I need is a single-time import.
Craftimport only allows XML and seems outdated and unmaitained.

**Tags:** entries, import, export


---

## 2 answers

### Answer by username_1 on 2023-07-31. Score: 3 | Accepted answer

You can write a simple migration that uses Craft's API to create entries programmatically. You can generate a new migration with the migrate/create console command:
php craft migrate/create content_import

This will create a new PHP file in the migrations/ folder. You can put the migration code inside the safeUp method. To execute the migration:
php craft migrate/up

Inside the migration, you need access to your JSON. You can put the entire JSON string inside the migration, but I usually don't want to have that much data in my source control. Instead, I like to put the JSON inside the migrations/ folder and load it inside the safeUp method:
$json = file_get_contents(__DIR__ . 'data.json');
$rows = json_decode($json, true, 512, JSON_THROW_ON_ERROR);

This means you need to place this file in the production server manually, but that's fine since it's a one-time operation.
Once the JSON is loaded, you can create entries through the Elements service:
$contentSection = \Craft::$app->sections->getSectionByHandle('myContentSection');
$contentEntryType = $contentSection->getEntryTypes()[0];

foreach ($rows as $row) {
    $entry = new \craft\elements\Entry();
    $entry->sectionId = $contentSection->Id;
    $entry->typeId = $contentEntryType->id;
    $entry->enabled = true;
    $entry->title = $row['title'];
    // Set more properties as needed, i.e. slug, postDate, etc.

    $entry->setFieldValues([
        'body' => $row['body'],
        // Set other custom fields
    ]);

    $success = \Craft::$app->elements->saveElement($entry);
    if (!$success) {
        \Craft::error('Couldn’t save the entry "' . $entry->title . '"', __METHOD__);
        return false;
    }
}

To test the migration repeatedly during migration, you need to modify the safeDown method. I like to put in code that deletes all the imported entries (careful, the following will delete all entries in the given section):
$content = \craft\elements\Entry::find()
    ->section('myContentSection')
    ->status(null)
    ->all();

foreach ($content as $entry) {
    \Craft::$app->elements->deleteElement($entry, true);
}

Then you can redo the migration for testing purposes like this:
php craft migrate/redo 1


This may look complicated, but is pretty simple and quick once you've done it a few times. If this seems daunting, Feed Me is probably the better option.


---

### Answer by username_2 on 2023-08-04. Score: 0

Personally, I'd use FeedMe. It's excellent. If you don't need it again just remove it after you have used it.


---

