dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.38k stars 4.75k forks source link

JSInterop: Consider JSType.Json for conveniently marshaling data #77784

Open lambdageek opened 2 years ago

lambdageek commented 2 years ago

consider some code like this:

public record Todo(int id, int userId, string title, bool completed);

public class SampleApp {
  public static async Task<Todo[]> GetTodos() { ... }
}

Right now to make use of something like that from JavaScript, we have to write some boilerplate:

public class SampleApp {
  [JSExport]
  public static Task<string> GetTodosExportWrapper() => JsonSerializer.SerializeAsync (await GetTodos());
}
   // in main.js
   const exports = await getAssemblyExports(...);
   const json = JSON.parse (await exports.SampleApp.GetTodosExportWrapper());

It would be nice if we had a convenience marshaler for moving Json blobs around:

  [JSExport]
  [return:JSMarshalAs<JSType.Promise<JSType.Json>>]
  public static Task<Todo[]> GetTodos() { ... }
  // in main.js
  const exports = await getAssemblyExports(...);
  const json = await exports.SampleApp.GetTodos ();
ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.

Issue Details
consider some code like this: ```csharp public record Todo(int id, int userId, string title, bool completed); public static async Task GetTodos() { ... } ``` Right now to make use of something like that from JavaScript, we have to write some boilerplate: ```csharp public class SampleApp { [JSExport] public static Task GetTodosExportWrapper() => JsonSerializer.SerializeAsync (await GetTodos()); } ``` ```js // in main.js const exports = await getAssemblyExports(...); const json = JSON.parse (await exports.SampleApp.GetTodosExportWrapper()); ``` It would be nice if we had a convenience marshaler for moving Json blobs around: ```csharp [JSExport] [return:JSMarshalAs>] public static Task GetTodos() { ... } ``` ```js // in main.js const exports = await getAssemblyExports(...); const json = await exports.SampleApp.GetTodos (); ```
Author: lambdageek
Assignees: -
Labels: `area-System.Text.Json`
Milestone: -
lambdageek commented 2 years ago

/cc @pavelsavara

ghost commented 2 years ago

Tagging subscribers to 'arch-wasm': @lewing See info in area-owners.md if you want to be subscribed.

Issue Details
consider some code like this: ```csharp public record Todo(int id, int userId, string title, bool completed); public class SampleApp { public static async Task GetTodos() { ... } } ``` Right now to make use of something like that from JavaScript, we have to write some boilerplate: ```csharp public class SampleApp { [JSExport] public static Task GetTodosExportWrapper() => JsonSerializer.SerializeAsync (await GetTodos()); } ``` ```js // in main.js const exports = await getAssemblyExports(...); const json = JSON.parse (await exports.SampleApp.GetTodosExportWrapper()); ``` It would be nice if we had a convenience marshaler for moving Json blobs around: ```csharp [JSExport] [return:JSMarshalAs>] public static Task GetTodos() { ... } ``` ```js // in main.js const exports = await getAssemblyExports(...); const json = await exports.SampleApp.GetTodos (); ```
Author: lambdageek
Assignees: -
Labels: `api-suggestion`, `arch-wasm`, `area-System.Runtime.InteropServices.JavaScript`
Milestone: Future
gregsdennis commented 2 years ago

Why not use STJ? Maybe I don't understand the use case.

FranklinWhale commented 2 years ago

Not sure how this will work with <RunAOTCompilation>true</RunAOTCompilation>. Currently, to make AOT work, I have to create a JsonSerializerContext. Otherwise, the following warning appears:

Using member System.Text.Json.JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions) which has RequiresUnreferencedCodeAttribute can break functionality when trimming application code. JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.

pavelsavara commented 2 years ago

Yes, we already have json trimming issue on Blazor https://github.com/dotnet/aspnetcore/issues/39839

Since we have code generator here, we could generate

[JsonSerializable(typeof(List<Item>))]
private partial class ItemListSerializerContext : JsonSerializerContext { }