[NotionAPI] NotionAPI simple code
소개
Notion의 DB를 API로 불러오는데 사용되는 코드입니다.
만약 해당DB에 특정 컬럼만 가져오고 싶다면 columnOrder
를 사용하여 컬럼의 순서 및 이름을 지정할 수 있습니다.
ex) columnOrder = new List<string> { "Name", "Age", "Email" };
사용된 라이브러리는 Newtonsoft.Json
,RestSharp
입니다.
using System.Data;
using Newtonsoft.Json.Linq;
using RestSharp;
public class NotionAPI
{
private string _apiKey;
private string _dbKey;
public NotionAPI(string apiKey, string dbKey)
{
_apiKey = apiKey;
_dbKey = dbKey;
}
/// <summary>
/// Notion API에서 데이터를 가져와 DataTable로 반환합니다.
/// </summary>
/// <returns>DataTable 형태의 노션 데이터</returns>
public async Task<DataTable> FetchDataAsDataTableAsync()
{
string jsonData = await FetchNotionDataAsync();
return ParseDataToDataTable(jsonData);
}
public async Task<DataTable> FetchDataAsDataTableAsync(List<string> columnOrder = null)
{
string jsonData = await FetchNotionDataAsync();
return ParseDataToDataTable(jsonData, columnOrder);
}
/// <summary>
/// Notion API에서 데이터를 가져와 List<Dictionary<string, string>>로 반환합니다.
/// </summary>
/// <returns>List<Dictionary<string, string>> 형태의 노션 데이터</returns>
public async Task<List<Dictionary<string, string>>> FetchDataAsListAsync()
{
string jsonData = await FetchNotionDataAsync();
return ParseDataToList(jsonData);
}
public async Task<List<Dictionary<string, string>>> FetchDataAsListAsync(List<string> columnOrder = null)
{
string jsonData = await FetchNotionDataAsync();
return ParseDataToList(jsonData, columnOrder);
}
private async Task<string> FetchNotionDataAsync()
{
var client = new RestClient($"https://api.notion.com/v1/databases/{_dbKey}/query");
var request = new RestRequest();
request.Method = Method.Post;
request.AddHeader("Authorization", $"Bearer {_apiKey}");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Notion-Version", "2021-05-13");
var response = await client.ExecuteAsync(request);
return response.Content;
}
private DataTable ParseDataToDataTable(string jsonData)
{
var jObject = JObject.Parse(jsonData);
var dataTable = new DataTable();
var firstResult = jObject["results"]?.FirstOrDefault() as JObject;
var properties = firstResult?["properties"] as JObject;
if (properties == null) return null;
foreach (var property in properties)
{
dataTable.Columns.Add(property.Key.Replace(" ", "_"));
}
foreach (var result in jObject["results"])
{
var row = dataTable.NewRow();
var propertyValues = ParseProperties(result["properties"] as JObject);
foreach (DataColumn column in dataTable.Columns)
{
row[column.ColumnName] = propertyValues.ContainsKey(column.ColumnName.Replace("_", " ")) ? propertyValues[column.ColumnName.Replace("_", " ")] : string.Empty;
}
dataTable.Rows.Add(row);
}
return dataTable;
}
/// <summary>
/// 컬럼의 순서 및 이름을 지정하여 DataTable로 반환합니다.
/// </summary>
/// <param name="jsonData"></param>
/// <param name="columnOrder"></param>
/// <returns></returns>
private DataTable ParseDataToDataTable(string jsonData, List<string> columnOrder)
{
var jObject = JObject.Parse(jsonData);
var dataTable = new DataTable();
var firstResult = jObject["results"]?.FirstOrDefault() as JObject;
var properties = firstResult?["properties"] as JObject;
if (properties == null) return null;
foreach (var column in columnOrder)
{
dataTable.Columns.Add(column);
}
foreach (var result in jObject["results"])
{
var row = dataTable.NewRow();
var propertyValues = ParseProperties(result["properties"] as JObject);
foreach (DataColumn column in dataTable.Columns)
{
row[column.ColumnName] = propertyValues.ContainsKey(column.ColumnName) ? propertyValues[column.ColumnName] : string.Empty;
}
dataTable.Rows.Add(row);
}
return dataTable;
}
private List<Dictionary<string, string>> ParseDataToList(string jsonData)
{
var jObject = JObject.Parse(jsonData);
var resultsList = new List<Dictionary<string, string>>();
foreach (var result in jObject["results"])
{
var propertyValues = ParseProperties(result["properties"] as JObject);
resultsList.Add(propertyValues);
}
return resultsList;
}
/// <summary>
/// 컬럼의 순서 및 이름을 지정하여 Dictionary로 반환합니다.
/// </summary>
/// <param name="jsonData"></param>
/// <param name="columnOrder"></param>
/// <returns></returns>
private List<Dictionary<string, string>> ParseDataToList(string jsonData, List<string> columnOrder)
{
var jObject = JObject.Parse(jsonData);
var resultsList = new List<Dictionary<string, string>>();
foreach (var result in jObject["results"])
{
var propertyValues = ParseProperties(result["properties"] as JObject);
var orderedPropertyValues = new Dictionary<string, string>();
foreach (var column in columnOrder)
{
orderedPropertyValues[column] = propertyValues.ContainsKey(column) ? propertyValues[column] : string.Empty;
}
resultsList.Add(orderedPropertyValues);
}
return resultsList;
}
private Dictionary<string, string> ParseProperties(JObject properties)
{
var parsedProperties = new Dictionary<string, string>();
foreach (var property in properties)
{
var value = property.Value as JObject;
var propertyType = value?["type"]?.ToString();
parsedProperties[property.Key] = propertyType switch
{
"title" => string.Join("", value["title"]?.Select(x => x["text"]?["content"]?.ToString()) ?? Enumerable.Empty<string>()),
"rich_text" => string.Join("", value["rich_text"]?.Select(x => x["text"]?["content"]?.ToString()) ?? Enumerable.Empty<string>()),
"number" => value["number"]?.ToString() ?? "",
"select" => value["select"]?["name"]?.ToString() ?? "",
"multi_select" => string.Join(", ", value["multi_select"]?.Select(x => x["name"].ToString()) ?? Enumerable.Empty<string>()),
"date" => value["date"]?["start"]?.ToString() ?? "",
"checkbox" => value["checkbox"]?.ToString() ?? "",
"url" => value["url"]?.ToString() ?? "",
"email" => value["email"]?.ToString() ?? "",
"phone_number" => value["phone_number"]?.ToString() ?? "",
"people" => string.Join(", ", value["people"]?.Select(x => x["name"]?.ToString()) ?? Enumerable.Empty<string>()),
"files" => string.Join(", ", value["files"]?.Select(x => x["name"]?.ToString()) ?? Enumerable.Empty<string>()),
"relation" => string.Join(", ", value["relation"]?.Select(x => x["id"]?.ToString()) ?? Enumerable.Empty<string>()),
"formula" => value["formula"]?["string"]?.ToString() ?? "",
"created_time" => value["created_time"]?.ToString() ?? "",
"created_by" => value["created_by"]?["name"]?.ToString() ?? "",
"last_edited_time" => value["last_edited_time"]?.ToString() ?? "",
"last_edited_by" => value["last_edited_by"]?["name"]?.ToString() ?? "",
"rollup" => value["rollup"]?["type"]?.ToString() == "array"
? string.Join(", ", value["rollup"]?["array"]?.Select(x => x["name"]?.ToString()) ?? Enumerable.Empty<string>())
: value["rollup"]?["number"]?.ToString() ?? "",
"status" => value["status"]?["name"]?.ToString() ?? "",
_ => ""
};
}
return parsedProperties;
}
}
Note: 만들고나니 내것이 아니었다.
Leave a comment