1

我正在使用新System.Text.Json库尝试将一些 json 直接反序列化为不可变类。

using System.Collections.Immutable;

public sealed class Book
{
    public int Id { get; }
    public string Name { get; }

    public Book(int id, string name)
    {
        Id = id;
        Name = name;
    }
}

public sealed class Author
{
    public int Id { get; }
    public string Firstname { get; }
    public string Lastname { get; }
    public ImmutableArray<Book> Books { get; }

    public Author(int id, string firstname, string lastname, ImmutableArray<Book> books)
    {
        Id = id;
        Firstname = firstname;
        Lastname = lastname;
        Books = books;
    }
}

默认情况下,无法构造对象,System.Text.Json因为它们没有空/默认构造函数,也没有任何公共设置器。

于是我开始构建 customJsonDecoder<T>来告诉库如何反序列化。

public class BookConverter : JsonConverter<Book>
{
    public override bool CanConvert(Type typeToConvert)
        => typeToConvert == typeof(Book);

    public override Book Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var rootElement = JsonDocument
            .ParseValue(ref reader)
            .RootElement;

        var id = rootElement.GetProperty(nameof(Book.Id).FirstToLower()).GetInt32();
        var name = rootElement.GetProperty(nameof(Book.Name).FirstToLower()).GetString();

        return new Book(id, name);
    }

    public override void Write(Utf8JsonWriter writer, Book value, JsonSerializerOptions options)
        => throw new NotImplementedException();
}

public class AuthorConverter : JsonConverter<Author>
{
    public override bool CanConvert(Type typeToConvert)
        => typeToConvert == typeof(Author);

    public override Author Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var rootElement = JsonDocument
            .ParseValue(ref reader)
            .RootElement;

        var id = rootElement.GetProperty(nameof(Author.Id).FirstToLower()).GetInt32();
        var firstname = rootElement.GetProperty(nameof(Author.Firstname).FirstToLower()).GetString();
        var lastname = rootElement.GetProperty(nameof(Author.Lastname).FirstToLower()).GetString();
        var books = rootElement.GetProperty(nameof(Author.Books).FirstToLower()).EnumerateArray().Select(e => ~~ ??? ~~).ToImmutableArray();

        return new Author(id, firstname, lastname);
    }

    public override void Write(Utf8JsonWriter writer, Author value, JsonSerializerOptions options)
        => throw new NotImplementedException();
}

但是在这里我被卡住了。在反序列化作者的书籍结束时。
我如何重用现有的JsonDecoder<Book>来反序列化该数组?
谢谢您的帮助!:)

4

1 回答 1

0

我想我在查看问题时找到了答案。:D

我只是将逻辑提取到一个可以从另一个转换器调用的静态函数中。

public class BookConverter : JsonConverter<Book>
{
    public override bool CanConvert(Type typeToConvert)
        => typeToConvert == typeof(Book);

    public override Book Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var rootElement = JsonDocument
            .ParseValue(ref reader)
            .RootElement;
        return GetBook(rootElement);
    }

    public static Book GetBook(JsonElement jsonElement)
    {
        var id = jsonElement.GetProperty(nameof(Book.Id).FirstToLower()).GetInt32();
        var name = jsonElement.GetProperty(nameof(Book.Name).FirstToLower()).GetString();

        return new Book(id, name);
    }

    public override void Write(Utf8JsonWriter writer, Book value, JsonSerializerOptions options)
        => throw new NotImplementedException();
}

public class AuthorConverter : JsonConverter<Author>
{
    public override bool CanConvert(Type typeToConvert)
        => typeToConvert == typeof(Author);

    public override Author Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var rootElement = JsonDocument
            .ParseValue(ref reader)
            .RootElement;

        var id = rootElement.GetProperty(nameof(Author.Id).FirstToLower()).GetInt32();
        var firstname = rootElement.GetProperty(nameof(Author.Firstname).FirstToLower()).GetString();
        var lastname = rootElement.GetProperty(nameof(Author.Lastname).FirstToLower()).GetString();
        var books = rootElement.GetProperty(nameof(Author.Books).FirstToLower()).EnumerateArray().Select(BookConverter.GetBook).ToImmutableArray();

        return new Author(id, firstname, lastname);
    }

    public override void Write(Utf8JsonWriter writer, Author value, JsonSerializerOptions options)
        => throw new NotImplementedException();
}
于 2019-11-22T12:32:28.287 回答