Как исключить свойство из сериализации в System.Text.Json.JsonSerializer.Serialize () с помощью JsonConverter - PullRequest
0 голосов
/ 26 октября 2019

Я хочу иметь возможность исключить свойство при сериализации с использованием System.Text.Json.JsonSerializer. Я не хочу использовать атрибут JsonIgnore везде, где я хочу это сделать. Я хотел бы иметь возможность определять свойства, которые я хочу исключить только во время сериализации, с помощью некоторого Fluent API, которого в настоящее время не существует.

Единственный вариант, который мне удалось найти, - это определить JsonConverter и добавьте его в список преобразователей в JsonSerializerOptions, который я передаю методу Serialize () следующим образом:

var options = new JsonSerializerOptions();
options.Converters.Add(new BookConverter());
json = JsonSerializer.Serialize(book, options);

В JsonConverter мне нужно было бы написать все представление JSON самостоятельно, используяUtf8JsonWriter, исключая свойство, которое я не хочу сериализовать. Это большая работа, чтобы просто исключить собственность. Несмотря на то, что JsonConverter - отличная функция расширяемости от команды .NET, он слишком низкоуровневый для моего случая использования. Кто-нибудь знает какой-либо другой способ добиться исключения свойства без необходимости записывать представление JSON самостоятельно?

Я не хочу делать следующее:

  • Используйте атрибут или динамически добавьте атрибут во время выполнения
  • Измените модификатор доступа к свойству на что-то вроде private или protected
  • Используйте стороннюю библиотеку, как моя проблемаразрешима, если я использую Json.NET.

Пример:

class Program
{
    void Main()
    {
        // We want to serialize Book but to ignore the Author property
        var book = new Book() { Id = 1, Name = "Calculus", Author = new Author() };

        var json = JsonSerializer.Serialize(book);
        // Default serialization, we get this:
        // json = { "Id": 1, "Name": "Calculus", "Author": {} }

        // Add our custom converter to options and pass it to the Serialize() method
        var options = new JsonSerializerOptions();
        options.Converters.Add(new BookConverter());
        json = JsonSerializer.Serialize(book, options);
        // I want to get this:
        // json = { Id: 1, Name: "Calculus" }
    }
}

public class Author { }

public class Book
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Author Author { get; set; }
}

public class BookConverter : JsonConverter<Book>
{
    public override Book Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // Use default implementation when deserializing (reading)
        return JsonSerializer.Deserialize<Book>(ref reader, options);
    }

    public override void Write(Utf8JsonWriter writer, Book value, JsonSerializerOptions options)
    {
        // Serializing. Here we have to write the JSON representation ourselves
        writer.WriteStartObject();

        writer.WriteNumber("Id", value.Id);
        writer.WriteString("Name", value.Name);
        // Don't write Author so we can exclude it

        writer.WriteEndObject();
    }
}

1 Ответ

0 голосов
/ 26 октября 2019

Так что я случайно наткнулся на статью, в которой демонстрируется, как использовать объект JsonDocument в новом пространстве имен System.Text.Json, и это следующая лучшая вещь для Fluent API. Вот как можно решить этот вопрос.

Метод BookConverter.Write ():

public override void Write(Utf8JsonWriter writer, Book value, JsonSerializerOptions options)
{
    writer.WriteStartObject();

    using (JsonDocument document = JsonDocument.Parse(JsonSerializer.Serialize(value)))
    {
        foreach (var property in document.RootElement.EnumerateObject())
        {
            if (property.Name != "Author")
                property.WriteTo(writer);
        }
    }

    writer.WriteEndObject();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...