Difference between revisions of "CSV Exporting"
| (4 intermediate revisions by the same user not shown) | |||
| Line 13: | Line 13: | ||
= CSV endpoint usage = | = CSV endpoint usage = | ||
Any /list endpoint is now available as /list.csv as well. For example, navigating to | Any /list endpoint is now available as /list.csv as well. For example, navigating to https://yoursite.com/v1/user/list.csv will provide a CSV of users, provided you have access to the endpoint through the user_list [[Permissions|permission grant]]. | ||
From the frontend this can then be done in a few ways: | From the frontend this can then be done in a few ways: | ||
| Line 28: | Line 28: | ||
import webRequest from 'UI/Functions/WebRequest'; | import webRequest from 'UI/Functions/WebRequest'; | ||
webRequest('user/list.csv').then(response => { | // As text: | ||
webRequest('user/list.csv', null, {rawText: true}).then(response => { | |||
// response.text | |||
}); | }); | ||
// As a blob (binary): | |||
webRequest('user/list.csv', null, {blob: true}).then(response => { | |||
// response.blob | |||
}); | |||
// It supports {where: {}} as well as query/ args just like regular list endpoints too. | |||
webRequest('user/list.csv', {query: 'AvatarRef!=?', args: ['']}, {rawText: true}).then(response => { | |||
// response.text | |||
}); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
= Omitting or renaming fields = | = Omitting or renaming fields = | ||
By default the CSV will include all the fields which would otherwise be present in the JSON. This is because it is based on the same field visibility mechanics as the regular JSON endpoints and does watch out for [JsonIgnore] attributes. When the CSV schema is loaded, it will pass each field through the BeforeCsvGettable event, similar to the BeforeGettable field event, which you can use to modify fields in a wide range of ways: | By default the CSV will include all the fields which would otherwise be present in the JSON. This is because it is based on the same field visibility mechanics as the regular JSON endpoints and does watch out for [JsonIgnore] attributes as well as [CsvIgnore] attributes. When the CSV schema is loaded, it will pass each field through the BeforeCsvGettable event, similar to the BeforeGettable field event, which you can use to modify fields in a wide range of ways: | ||
| Line 42: | Line 52: | ||
using Api.Startup; | using Api.Startup; | ||
using Api.Contexts; | |||
using Api.CsvExport; | |||
using Api.Eventing; | |||
using System.Threading.Tasks; | |||
using Api.Users; | |||
namespace Api.MyCsvEvents | namespace Api.MyCsvEvents | ||
| Line 55: | Line 71: | ||
/// EventListeners are instanced automatically during startup. | /// EventListeners are instanced automatically during startup. | ||
/// </summary> | /// </summary> | ||
public | public CsvEventSetup() | ||
{ | { | ||
Events.User.BeforeCsvGettable.AddEventListener((Context context, CsvFieldMap<User> csvField) => { | Events.User.BeforeCsvGettable.AddEventListener((Context context, CsvFieldMap<User> csvField) => { | ||
| Line 75: | Line 91: | ||
} | } | ||
// can also set csvField.AdvancedHandler to specify a value rewrite function | // can also set csvField.AdvancedHandler to specify a value rewrite function (see below) | ||
return new ValueTask<CsvFieldMap<User>>(csvField); | return new ValueTask<CsvFieldMap<User>>(csvField); | ||
| Line 82: | Line 98: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | |||
= Field value rewriting = | |||
If you would like to rewrite the value that actually appears in the CSV, use the above technique to obtain the field you want to rewrite the value for and then set an AdvancedHandler on it, like so: | |||
<syntaxhighlight lang="csharp"> | |||
// Non-async: | |||
csvField.AdvancedHandler = (User user, CsvWriter writer) => { | |||
writer.WriteField("#" + user.Id); | |||
return new ValueTask(); | |||
}; | |||
// Async: | |||
csvField.AdvancedHandler = async (User user, CsvWriter writer) => { | |||
// ..do something slow.. | |||
writer.WriteField("#" + user.Id); | |||
}; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Latest revision as of 13:24, 4 October 2022
Sometimes it is useful to have your site data exportable as a CSV. Due to the generic way SocialStack handles database content, exporting a CSV requires little to get it going.
Installing CSV Exporter
Install the API module:
socialstack install Api/CsvExport
And that's it! You can now use the .csv endpoints
CSV endpoint usage
Any /list endpoint is now available as /list.csv as well. For example, navigating to https://yoursite.com/v1/user/list.csv will provide a CSV of users, provided you have access to the endpoint through the user_list permission grant.
From the frontend this can then be done in a few ways:
- As a simple link, often from a custom admin panel component:
<a href='/v1/user/list.csv' target='_blank'>Download user data</a>
- Via webRequest (or fetch):
import webRequest from 'UI/Functions/WebRequest';
// As text:
webRequest('user/list.csv', null, {rawText: true}).then(response => {
// response.text
});
// As a blob (binary):
webRequest('user/list.csv', null, {blob: true}).then(response => {
// response.blob
});
// It supports {where: {}} as well as query/ args just like regular list endpoints too.
webRequest('user/list.csv', {query: 'AvatarRef!=?', args: ['']}, {rawText: true}).then(response => {
// response.text
});
Omitting or renaming fields
By default the CSV will include all the fields which would otherwise be present in the JSON. This is because it is based on the same field visibility mechanics as the regular JSON endpoints and does watch out for [JsonIgnore] attributes as well as [CsvIgnore] attributes. When the CSV schema is loaded, it will pass each field through the BeforeCsvGettable event, similar to the BeforeGettable field event, which you can use to modify fields in a wide range of ways:
using Api.Startup;
using Api.Contexts;
using Api.CsvExport;
using Api.Eventing;
using System.Threading.Tasks;
using Api.Users;
namespace Api.MyCsvEvents
{
/// <summary>
/// EventListeners are instanced automatically during startup.
/// The class and namespace can be anything - it just needs to have the attribute.
/// </summary>
[EventListener]
public partial class CsvEventSetup
{
/// <summary>
/// EventListeners are instanced automatically during startup.
/// </summary>
public CsvEventSetup()
{
Events.User.BeforeCsvGettable.AddEventListener((Context context, CsvFieldMap<User> csvField) => {
if(csvField == null)
{
// something else already filtered it out. Do nothing.
return new ValueTask<CsvFieldMap<User>>(csvField);
}
if(csvField.Name == "RevisionId")
{
// returning a null will effectively remove this field from the CSV.
csvField = null;
}
else if(csvField.Name == "Id")
{
// Changing the name of the field will rename it in the CSV.
csvField.Name = "Socialstack Site Id";
}
// can also set csvField.AdvancedHandler to specify a value rewrite function (see below)
return new ValueTask<CsvFieldMap<User>>(csvField);
});
}
}
}
Field value rewriting
If you would like to rewrite the value that actually appears in the CSV, use the above technique to obtain the field you want to rewrite the value for and then set an AdvancedHandler on it, like so:
// Non-async:
csvField.AdvancedHandler = (User user, CsvWriter writer) => {
writer.WriteField("#" + user.Id);
return new ValueTask();
};
// Async:
csvField.AdvancedHandler = async (User user, CsvWriter writer) => {
// ..do something slow..
writer.WriteField("#" + user.Id);
};