If no export tools exist for your current blogging system you’ll need to create one that generates a JSON file as described here. There is a full example at the end of this file. Please note that your final JSON file should have no comments in the final format. Those are only included here for readability and explanatory purposes.
JSON file structure
First and foremost, your JSON file must contain valid JSON. You can test your file is valid using the JSONLint online tool.
The file structure can optionally be wrapped in:
{
"db": [...contents here...]
}
Both with and without are valid Ghost JSON files. But you must include a meta
and a data
object.
The meta object
"meta": {
"exported_on":1408552443891,
"version":"2.14.0"
}
The meta
block expects two keys, exported_on
and version
. exported_on
should be an epoch timestamp in milliseconds, version should be the Ghost version the import is valid for.
The data block
Ghost’s JSON format mirrors the underlying database structure, rather than the API, as it allows you to override fields that the API would ignore.
"data": {
"posts": [{...}, ...],
"tags": [],
"users": [],
"posts_tags": [],
"posts_authors": [],
"roles_users": []
}
The data block contains all of the individual post, tag, and user resources that you want to import into your site, as well as the relationships between all of these resources. Each item that you include should be an array of objects.
Relationships can be defined between posts and tags, posts and users (authors) and between users and their roles.
IDs inside the file are relative to the file only, so if you have a post
with id: 1
and a posts_tags
object which references post_id: 1
, then those two things will be linked, but they do not relate to the post
with id: 1
in your database.
Example
{
"meta":{
// epoch time in milliseconds
"exported_on": 1388805572000,
"version": "2.14.0"
},
"data":{
"posts": [
{
"id": 1,
"title": "my blog post title",
"slug": "my-blog-post-title", // Optional, will be generated by Ghost if missing
// Lexical is used to represent your content
"lexical": "{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hello, beautiful world! 👋\",\"type\":\"extended-text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}",
"feature_image": null,
"feature_image_alt": null,
"feature_image_caption": null,
"featured": 0, // boolean indicating featured status
"page": 0, // boolean indicating if this is a page or post
"status": "published", // or draft
"published_at": 1283780649000, // epoch time in milliseconds
"published_by": 1, // the first user created has an id of 1
"meta_title": null,
"meta_description":null,
"email_only": false, // boolean indicating email-only type of post
"author_id": 1, // the first user created has an id of 1
"created_at": 1283780649000, // epoch time in milliseconds
"created_by": 1, // the first user created has an id of 1
"updated_at": 1286958624000, // epoch time in milliseconds
"updated_by": 1 // the first user created has an id of 1
}
],
"tags": [
{
"id": 5,
"name": "Colorado Ho!",
"slug": "colorado-ho", // Optional, will be generated by Ghost if missing
"description": ""
}
],
"posts_tags": [
{"tag_id": 5, "post_id": 1},
],
"users": [
{
"id": 3,
"name": "Jo Bloggs",
"slug": "jo-blogs", // Optional, will be generated by Ghost if missing
"email": "jo@example.com",
"profile_image": null,
"cover_image": null,
"bio": null,
"website": null,
"location": null,
"accessibility": null,
"meta_title": null,
"meta_description": null,
"created_at": 1283780649000, // epoch time in millis
"created_by": 1,
"updated_at": 1286958624000, // epoch time in millis
"updated_by": 1
}
],
// Provide this if you want different roles to the default "Author" role
"roles_users": [
{
"user_id": 2,
"role_id": ObjectId // This must reference the id from your database
}
]
}
}