1.0.4 • Published 1 year ago

notion-json-converter v1.0.4

Weekly downloads
-
License
MIT
Repository
-
Last release
1 year ago

notion-json-lens

A bi-directional converter between Notion's DB properties and a simple plain JSON object.

Motivation

Notion's type objects definition for a DB items' properties can be tricky to work with. To get the value of any column, you need to know it's type and the object format of that type accordind to the Type Objects Reference.

For example. A column of type Text in a notion DB is represented as:

{
    ...
    "properties": {
        "column_name": {
            "id": "HbZT",
            "type": "rich_text",
            "rich_text": [
                {
                "type": "text",
                "text": {
                    "content": "There is some text here",
                    "link": null
                },
                "annotations": {
                    "bold": false,
                    "italic": false,
                    "strikethrough": false,
                    "underline": false,
                    "code": false,
                    "color": "default"
                },
                "plain_text": "There is some text here",
                "href": null
                },
            ]
        }
    }
}

To get the column's value you need to use item.properties.column_name.rich_text[0].plain_text 😰 (not to mention specific cases like if there are multiple blocks of rich_text in there).

Most times you just need a simple path to access an item's properties such as item.properties.column_name with no need to worry about the type of that columnm.

This is where this library comes in.

How it works

The lens provides transformation in two directions, each implemented with a different function:

  • notionToJson
  • jsonToNotion

The lens will only be applied to the properties node of the item. Other data points outside the properties object are not contemplated in the transformation.

The name of the columns and json fields is preserved during a transformation. The lens is agnostic on the naming convention of the DB and object model, not performing any alterations on the columns and fields names, just its contents.

Notion to JSON

Transforms a Notion DB item properties object into a flat JSON.

Transformed types:

  • Title
  • Text
  • Number
  • Select
  • Multi Select
  • Status
  • Date
  • Checkbox
  • URL
  • Unique Id

Columns with types not in the list above are returned as-is to preserve information. Support to more types coming in the future...

import { notionToJson } from "notion-json-converter";

const sampleNotionDbProperties = {
    Title: {
        id: "title",
        type: "title",
        title: [
            {
                type: "text",
                text: {
                    content: "page 1",
                    link: null,
                },
                annotations: {
                    bold: false,
                    italic: false,
                    strikethrough: false,
                    underline: false,
                    code: false,
                    color: "default",
                },
                plain_text: "page 1",
                href: null,
            },
        ],
    },
    Description: {
        id: "HbZT",
        type: "rich_text",
        rich_text: [
            {
                type: "text",
                text: {
                    content: "There is some ",
                    link: null,
                },
                annotations: {
                    bold: false,
                    italic: false,
                    strikethrough: false,
                    underline: false,
                    code: false,
                    color: "default",
                },
                plain_text: "There is some ",
                href: null,
            },
            {
                type: "text",
                text: {
                    content: "text",
                    link: null,
                },
                annotations: {
                    bold: true,
                    italic: false,
                    strikethrough: false,
                    underline: false,
                    code: false,
                    color: "default",
                },
                plain_text: "text",
                href: null,
            },
            {
                type: "text",
                text: {
                    content: " in this property!",
                    link: null,
                },
                annotations: {
                    bold: false,
                    italic: false,
                    strikethrough: false,
                    underline: false,
                    code: false,
                    color: "default",
                },
                plain_text: " in this property!",
                href: null,
            },
        ],
    },
    Number: {
        id: "DT%3Eg",
        type: "number",
        number: 2,
    },
    Select: {
        id: "FSau",
        type: "select",
        select: {
            id: "b5b79bb7-e513-4513-9c0f-8cf81392b189",
            name: "option 1",
            color: "red",
        },
    },
    "Multi Select": {
        id: "%3EP%60%7D",
        type: "multi_select",
        multi_select: [
            {
                id: "82303241-ae20-4690-bd0b-349a1528954c",
                name: "option 2",
                color: "red",
            },
            {
                id: "d521ee51-b4ad-468d-979a-d230875c1cf8",
                name: "option 1",
                color: "green",
            },
        ],
    },
    Status: {
        id: "ynbl",
        type: "status",
        status: {
            id: "13edf371-8bb1-4d19-921d-a095831dfab0",
            name: "Done",
            color: "green",
        },
    },
    Date: {
        id: "MJSZ",
        type: "date",
        date: {
            start: "2024-03-16T00:00:00.000-05:00",
            end: "2024-03-17T00:00:00.000-05:00",
            time_zone: null,
        },
    },
    Checkbox: {
        id: "jWlx",
        type: "checkbox",
        checkbox: true,
    },
    URL: {
        id: "jWlx",
        type: "url",
        url: "https://www.notion.so",
    },
};

console.log(notionToJson(baseNotionObject.properties));

// Output:
// {
//     Title: "page 1",
//     Description: "There is some text in this property!",
//     Number: 2,
//     Select: "option 1",
//     "Multi Select": ["option 2", "option 1"],
//     Status: "Done",
//     Date: {
//         start: "2024-03-16T00:00:00.000-05:00",
//         end: "2024-03-17T00:00:00.000-05:00",
//     },
//     Checkbox: true,
//     URL: "https://www.notion.so",
// }

JSON to Notion

Transforms a JSON object that respects the format below to a properties node of a Notion DB item.

Transformed types:

  • Title
  • Text
  • Number
  • Select
  • Multi Select
  • Status
  • Date
  • Checkbox
  • URL

Unique Id is not supported in the JSON to Notion flow since the Id is not editable in Notion.

This side of the lens requires the Notion Table's schema to get the type information of each field and perform the appropriate conversion. The schema passed is the response of the Retrieve Database endpoint of Notion's API.

import { Client } from "@notionhq/client"; // standard Notion API client
import { jsonToNotion } from "notion-json-converter";

const notion = new Client({ auth: <YOUR NOTION API SECRET> });

(async () => {

    const dbSchema = await notion.databases.retrieve({
        database_id: <your database_id>,
    });

    const json = {
        Title: "page 1",
        Description: "There is some **text** in this property!",
        Number: 2,
        Select: "option 1",
        "Multi Select": ["option 2", "option 1"],
        Status: "Done",
        Date: {
            start: "2024-03-16T00:00:00.000-05:00",
            end: "2024-03-17T00:00:00.000-05:00",
        },
        Checkbox: true,
        URL: "https://www.notion.so",
    };

    console.log(jsonToNotion(json, dbSchema));

})()

// Output
// {
//   "Title": {
//       "title": [
//           {
//               "text": {
//                   "content": "page 1"
//               }
//           }
//       ]
//   },
//   "Number": {
//       "number": 2
//   },
//   "Select": {
//       "select": {
//           "name": "option 1"
//       }
//   },
//   "Multi Select": {
//       "multi_select": [
//           {
//               "name": "option 2"
//           },
//           {
//               "name": "option 1"
//           }
//       ]
//   },
//   "Status": {
//       "status": {
//           "name": "Done"
//       }
//   },
//   "Date": {
//       "date": {
//           "start": "2024-03-16T00:00:00.000-05:00",
//           "end": "2024-03-17T00:00:00.000-05:00"
//       }
//   },
//   "Checkbox": {
//       "checkbox": true
//   },
//   "URL": {
//       "url": "https://www.notion.so"
//   }
// }

Known issues

  • Currently the formatting information in rich_text columns is lost in the conversion. One idea is to use Markdown notation in the JSON side to represent markups supported by Notion, however this is not implemented yet
  • Not all Notion types are currently contemplated in the conversion. I decided to start with the ones I use the most for simplicity and add support to additional types as needed
    • If you are interested in using this lib with an unsupported type, let me know or open a pull request 😁
  • There's no validation of the JSON schema received as input in the JSON to Notion flow. Ideally, the lib would validate if the JSON fields respect the expected format before attempting to convert to avoid any exceptions. Also in the roadmap for the future

Shout-outs

The name of this project was inspired by Ink and Switch's Project Cambria even though the actual implementation is different.

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago