Как преобразовать экземпляр класса в JsonDocument? - PullRequest
1 голос
/ 02 апреля 2020

Допустим, у нас есть класс сущностей, который выглядит следующим образом:

public class SerializedEntity
{
    public JsonDocument Payload { get; set; }

    public SerializedEntity(JsonDocument payload)
    {
        Payload = payload;
    }
}

Согласно n psql это создает таблицу со столбцом payload типа jsonb для этого класса, который является правильным.

Теперь я хотел бы взять любой экземпляр класса и сохранить его как payload в этой таблице, например:

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))

Ответы [ 4 ]

2 голосов
/ 02 апреля 2020

Сортируйте его, а затем анализируйте в JsonDocument.

var doc = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(
                new Pizza {Name = "Calzone", Size = 10}));
1 голос
/ 03 апреля 2020

Если ваша сущность EF (SerializedEntity) всегда будет иметь Pizza в качестве сериализованного документа JSON, то вы можете просто использовать POCO mapping - заменить свойство JsonDocument на свойство Pizza и отобразить это столбец jsonb.

Если фактические типы, которые вы хотите, различаются (иногда Pizza, иногда что-то еще), вы также можете сопоставить свойство object с jsonb и назначить ему любое значение. Npg sql внутренне сериализует любой объект в 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; }
}
1 голос
/ 02 апреля 2020

С 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)));

С тех пор (я думаю) встроено в ядро ​​tnet v3.0, так что вам не нужны никакие дополнительные сторонние библиотеки. Только не забудьте про using s.

. Возможно, есть некоторые хитрости, чтобы сделать анализ немного более эффективным (используя asyn c API, возможно, или как Магнус предлагает сериализовать в двоичный файл, используя SerializeToUtf8Bytes).

Мне не удалось найти какой-либо подход, который бы напрямую шел от T или object к JsonDocument. И я не могу поверить, что это не возможно как-то. Пожалуйста, оставьте комментарий, если вы знаете, как это работает, или добавьте свой ответ.

0 голосов
/ 03 апреля 2020

Окончательное решение для меня:

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}));
}
...