If you want to use Drupal as a CMS over your existing proprietary or open source CMS, then you’ll have to go through the migration process.
The Drupal community provides an excellent framework called “Migrate” to simplify migration processes. The Migrate framework provides multiple ways to migrate source content into your Drupal site. JSON source migration is one of the most powerful methods of migration.
With the traditional method, we used to migrate content using a CSV file, which required a lot of tasks to be completed before source mapping, e.g:
Only after doing all this can we go ahead with migration steps, like field mapping, etc. This sounds like a big pain!
I’ve been thinking constantly about the future of Drupal migration without interacting with SQL, and having random off-and-on conversations with a few lead developers in my circles. I’d like to share my experience with JSON source migration, which helped me save a lot of time and effort in site migration.
For JSON migration, we only need a JSON source URL. That’s it!
Let me show you how!
Prerequisite
Install the Migrate module from here: https://www.drupal.org/project/migrate
In this tutorial we’ll be creating a custom migration module to handle the migration process. In my case, I’ll be migrating movies from the JSON source to my Drupal movies content type, where I’ll be importing data into some text fields, taxonomy terms and an image field.
We will be using the following functions from the Migrate framework:
Create custom module movie_migration_example
Create movie_migration_example.info file
name: "Movies Migration"
description: "Module to migrate content from JSON source"
package: "Custom"
core: 7.x
dependencies[] = migrate
dependencies[] = field
dependencies[] = file
dependencies[] = image
dependencies[] = number
dependencies[] = text
files[] = movies_migration.module
files[] = MoviesMigration.inc
Create movie_migration_example.module file
<?php
/**
* Implements hook_migrate_api()
*/
function movies_migration_migrate_api() {
$api = array(
'api' => 2,
'migrations' => array(
'MoviesMigration' => array('class_name' => 'MoviesMigration'),
),
);
}
Now, we’ll create our JSON source migration class MoviesMigration.inc
<?php
/**
* @file
* Define a MoviesMigration Migration class for node migration.
*/
class MoviesMigration extends Migration {
....
}
Now, we’ll add unique ID map to our class using __construct. In my case, I have unique source ID in varchar.
<?php
/**
* @file
* Define a MoviesMigration Migration class for node migration.
*/
class MoviesMigration extends Migration {
/**
* A constructor.
*/
public function __construct($arguments) {
parent::__construct($arguments);
// Map for the migration.
$this->map = new MigrateSQLMap($this->machineName,
array(
'imdb_id' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'description' => 'Movie ID',
),
),
MigrateDestinationNode::getKeySchema()
);
}
}
Now add mapping:
<?php
/**
* @file
* Define a MoviesMigration Migration class for node migration.
*/
class MoviesMigration extends Migration {
/**
* A constructor.
*/
public function __construct($arguments) {
parent::__construct($arguments);
// Map for the migration.
$this->map = new MigrateSQLMap($this->machineName,
array(
'imdb_id' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'description' => 'Movie ID',
),
),
MigrateDestinationNode::getKeySchema()
);
$source_url = http://www.example.com/data/json/movies.json
$this->source = new MigrateSourceJSON($source_url, 'imdb_id', $this->fields());
// Destination node type is movies.
$this->destination = new MigrateDestinationNode('movies');
// Map node's title field to the title in the json content.
$this->addFieldMapping('title', 'title');
// Map node's body field to the content in the json content.
$this->addFieldMapping('body', 'plot');
// Map node's field_id field to the id in the json content.
$this->addFieldMapping('field_imdb_id', 'imdb_id');
// Map node's field_poster to the poster in the json content.
$this->addFieldMapping('field_poster', 'poster');
// Map node's field_genre field to the genre in the json content.
$this->addFieldMapping('field_genre', 'genre')
->separator(',');
$this->addFieldMapping('field_genre:create_term')
->defaultValue(TRUE);
// Hide comments.
$this->addFieldMapping('comment', NULL)->defaultValue(COMMENT_NODE_CLOSED);
}
/**
* Return the fields (this is cleaner than passing in the array
* in the MigrateSourceJSON class above)
* @return array
*/
function fields() {
return array(
'title' => 'The title of the content',
'plot' => 'The body of the content',
'poster' => 'Image Source url associated with the content',
'imdb_id' => 'IMDB ID associated with the content',
'genre' => 'Genre associated with the content',
);
}
}
That’s it!
Now, you just need to complete the following steps to import content using your migration class.
Using JSON API migration, you don’t need to worry about data structure as JSON already provides data in a structured way. Also, you don’t need to worry about SQL skills, which would be required in the case of database migration to pull data from the source database in a structured way, so that it can be migrated without errors or broken data. JSON migration also saves you from having to write a lot of code—you just need a source URL and you’re good to go.
Hurray!
If you have any questions, please feel free to comment.