如何将 class 实例转换为 JsonDocument?
How to convert a class instance to JsonDocument?
假设我们有一个如下所示的实体 class:
public class SerializedEntity
{
public JsonDocument Payload { get; set; }
public SerializedEntity(JsonDocument payload)
{
Payload = payload;
}
}
根据 npsql,这会生成一个 table,其列 payload
的类型为 jsonb
,此 class 是正确的。
现在我想做的是获取 any class 实例并将其作为 payload
存储在此 table 中,例如:
public class Pizza {
public string Name { get; set; }
public int Size { get; set; }
}
然后应该可以作为具有以下结构的对象进行检索:
{Name: "name", Size: 10}
所以我需要这样的东西:
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(someConverter.method(pizza))
使用 System.Text.Json 有点尴尬但可能:
using System.Text.Json;
using System.Text.Json.Serialization;
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(JsonDocument.Parse(JsonSerializer.Serialize(pizza)));
它自(我认为)v3.0 以来就已内置到 dotnet 核心中,因此您不需要任何额外的第 3 方库。只是不要忘记 using
s.
尽管如此(使用异步 API,也许或如 Magnus 建议的那样,使用 SerializeToUtf8Bytes
序列化为二进制文件)可能有一些技巧可以使解析更有效一些。
我还没有找到任何直接从 T
或 object
到 JsonDocument
的方法。 而且我不能相信这是不可能的。如果您知道它是如何工作的或添加您的答案,请发表评论。
对其进行序列化,然后将其解析为 JsonDocument。
var doc = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(
new Pizza {Name = "Calzone", Size = 10}));
如果您的 EF 实体 (SerializedEntity
) 始终将 Pizza 作为其序列化 JSON 文档,那么您只需使用 POCO mapping - 替换 JsonDocument 属性披萨 属性,并将其映射到 jsonb 列。
如果您想要的实际类型有所不同(有时是 Pizza,有时是其他类型),您还可以将 object
属性 映射到 jsonb,然后将您想要的任何内容分配给它。 Npgsql 将在内部将任何对象序列化为 JSON:
class Program
{
static void Main()
{
using var ctx = new BlogContext();
ctx.Database.EnsureDeleted();
ctx.Database.EnsureCreated();
ctx.FoodEntities.Add(new FoodEntity { SomeJsonFood = new Pizza { Name = "Napoletana" } });
ctx.FoodEntities.Add(new FoodEntity { SomeJsonFood = new Sushi { FishType = "Salmon" } });
ctx.SaveChanges();
}
}
public class BlogContext : DbContext
{
public DbSet<FoodEntity> FoodEntities { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("...");
}
public class FoodEntity
{
public int Id { get; set; }
public string Name { get; set; }
[Column(TypeName = "jsonb")]
public object SomeJsonFood { get; set; }
}
public class Pizza
{
public string Name { get; set; }
public int Size { get; set; }
}
public class Sushi
{
public string FishType { get; set; }
}
我的最终解决方案:
public class SerializedEntity
{
public object? Payload { get; set; }
public SerializedEntity(object? payload)
{
Payload = payload;
}
}
及其 EF 配置:
public void Configure(EntityTypeBuilder<SerializedEntity> builder)
{
builder.Property(n => n.Payload).HasColumnType("jsonb").HasConversion(
v => JsonConvert.SerializeObject(v,
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}),
v => JsonConvert.DeserializeObject<object?>(v,
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}));
}
您可以使用 .NET 6 中添加的 JsonSerializer.SerializeToDocument。在您的情况下,您最终会得到:
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(JsonSerializer.SerializeToDocument(pizza))
假设我们有一个如下所示的实体 class:
public class SerializedEntity
{
public JsonDocument Payload { get; set; }
public SerializedEntity(JsonDocument payload)
{
Payload = payload;
}
}
根据 npsql,这会生成一个 table,其列 payload
的类型为 jsonb
,此 class 是正确的。
现在我想做的是获取 any class 实例并将其作为 payload
存储在此 table 中,例如:
public class Pizza {
public string Name { get; set; }
public int Size { get; set; }
}
然后应该可以作为具有以下结构的对象进行检索:
{Name: "name", Size: 10}
所以我需要这样的东西:
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(someConverter.method(pizza))
使用 System.Text.Json 有点尴尬但可能:
using System.Text.Json;
using System.Text.Json.Serialization;
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(JsonDocument.Parse(JsonSerializer.Serialize(pizza)));
它自(我认为)v3.0 以来就已内置到 dotnet 核心中,因此您不需要任何额外的第 3 方库。只是不要忘记 using
s.
尽管如此(使用异步 API,也许或如 Magnus 建议的那样,使用 SerializeToUtf8Bytes
序列化为二进制文件)可能有一些技巧可以使解析更有效一些。
我还没有找到任何直接从 T
或 object
到 JsonDocument
的方法。 而且我不能相信这是不可能的。如果您知道它是如何工作的或添加您的答案,请发表评论。
对其进行序列化,然后将其解析为 JsonDocument。
var doc = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(
new Pizza {Name = "Calzone", Size = 10}));
如果您的 EF 实体 (SerializedEntity
) 始终将 Pizza 作为其序列化 JSON 文档,那么您只需使用 POCO mapping - 替换 JsonDocument 属性披萨 属性,并将其映射到 jsonb 列。
如果您想要的实际类型有所不同(有时是 Pizza,有时是其他类型),您还可以将 object
属性 映射到 jsonb,然后将您想要的任何内容分配给它。 Npgsql 将在内部将任何对象序列化为 JSON:
class Program
{
static void Main()
{
using var ctx = new BlogContext();
ctx.Database.EnsureDeleted();
ctx.Database.EnsureCreated();
ctx.FoodEntities.Add(new FoodEntity { SomeJsonFood = new Pizza { Name = "Napoletana" } });
ctx.FoodEntities.Add(new FoodEntity { SomeJsonFood = new Sushi { FishType = "Salmon" } });
ctx.SaveChanges();
}
}
public class BlogContext : DbContext
{
public DbSet<FoodEntity> FoodEntities { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("...");
}
public class FoodEntity
{
public int Id { get; set; }
public string Name { get; set; }
[Column(TypeName = "jsonb")]
public object SomeJsonFood { get; set; }
}
public class Pizza
{
public string Name { get; set; }
public int Size { get; set; }
}
public class Sushi
{
public string FishType { get; set; }
}
我的最终解决方案:
public class SerializedEntity
{
public object? Payload { get; set; }
public SerializedEntity(object? payload)
{
Payload = payload;
}
}
及其 EF 配置:
public void Configure(EntityTypeBuilder<SerializedEntity> builder)
{
builder.Property(n => n.Payload).HasColumnType("jsonb").HasConversion(
v => JsonConvert.SerializeObject(v,
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}),
v => JsonConvert.DeserializeObject<object?>(v,
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}));
}
您可以使用 .NET 6 中添加的 JsonSerializer.SerializeToDocument。在您的情况下,您最终会得到:
var pizza = new Pizza("Margharita", 10);
var se = new SerializedEntity(JsonSerializer.SerializeToDocument(pizza))