使用System.Text.Json将匿名对象序列化

4
我是一个有用的助手,能够翻译文本。
我正在开发一个ASP .Net Core 3.1应用程序,将另一个使用2.2的代码部分移植过来。到目前为止,我想从NewtonSoft JSON序列化库切换到新的System.Text.Json,但我遇到了一些问题。
考虑一个函数,用于提供带有此返回类型的HTTP-GET服务:
    [HttpGet("myservice")]
    public async Task<ActionResult<object>> GetDataAsync( ...

然后,最后一部分可以描述如下:
        var items = new List<IMyInterface>();
        int totalCount = ...
        int min = ...
        int max = ...

        return new ActionResult<object>(new
        {
            totalCount,
            min,
            max,
            items
        });

然而,它并没有起作用:项目集合按其声明类型(IMyInterface)进行序列化,而不是实际类型。我在这里读到,这是一种预期的行为,尽管对我来说不是很直观。
我的问题是:是否有任何方便而可靠的方法来利用新的序列化程序,即使处理匿名对象? 我希望避免每次都创建一个特定对象,而是可以内联组成结果。
更新:
这样做似乎可以解决问题,但看起来真的很丑:
        return new ActionResult<object>(new
        {
            totalCount,
            min,
            max,
            items = items.Cast<object>()
        });

你可以看一下这两个 GitHub 上的问题 (1, 2)。它们可能会对你有所帮助。但是似乎这是多态反序列化中故意设置的“特性”。 - fredrik
@Jawad 我更新了帖子,对每个项目进行了强制转换:它可以工作,但看起来相当丑陋。然而,通过对整个集合进行强制转换,它无法工作。 - Mario Vernari
@Jawad 不行:它不起作用。 - Mario Vernari
items = items.Cast<object>(),确实有效:https://dotnetfiddle.net/KxWHTu。这有点令人惊讶。我理解为什么他们不想支持多态反序列化,因为它会使服务器容易受到[Friday the 13th JSON attacks](https://dev59.com/glUM5IYBdhLWcg3wSexQ)的攻击。但是,除非声明类型是“object”,否则序列化声明类型而不是实际类型似乎很奇怪。至少数据合同序列化程序会在出现意外类型时抛出异常,而不仅仅将其序列化为基本类型。 - dbc
@dbc 我通过浏览器消耗服务器数据:我不需要类型名称在网络世界中暴露。我猜选项中的简单启用/禁用标志可能适合这个空洞。 - Mario Vernari
显示剩余5条评论
1个回答

2
如果您想序列化对象,为什么不将它们初始化为对象呢?是否有创建强类型对象的要求?

DotNetFiddler

    public static void Test()
    {
        var items = new List<object>() { new Class1 { Foo = "foo1", Bar1 = "Bar1" }, new Class2 { Foo = "foo1", Bar2 = "Bar2" } };
        int totalCount = 1;
        int min = 2;
        int max = 3;


        var root = new
        {
            totalCount,
            min,
            max,
            items,
        };

        var json = JsonSerializer.Serialize<object>(root, new JsonSerializerOptions { WriteIndented = true, });

        Console.WriteLine(json);
    }

如果您将项目创建为List<object>,则无需更改或执行任何操作。这可能是一种更清晰的方法,而不是在创建对象时将每个项目强制转换为对象。

这是解决问题的另一种方式。在我的情况下,许多这些集合都是由Linq表达式生成的,因此我必须应用Cast<object>()。但我仍然不明白为什么使用object可以进行序列化:为什么不始终使用运行时类型? - Mario Vernari
我知道newtonsoft json.net运行良好... System.text.json存在问题。 - Jawad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接