【问题标题】:How to deserialize Arraylist items into concrete type using System.Text.Json?如何使用 System.Text.Json 将 Arraylist 项反序列化为具体类型?
【发布时间】:2021-08-15 19:55:33
【问题描述】:

我有以下测试类

public class Test
{
    public int MyProperty { get; set; }            
    public ArrayList list { get; set; }
}
public class Employee
{
    public int MyProperty { get; set; }
    public string Name { get; set; }
}

以及下面的代码

static void Main(string[] args)
{
    Employee e1 = new Employee();
    e1.MyProperty = 1;
    e1.Name = "Yash";
    Employee e2 = new Employee();
    e2.MyProperty = 1;
    e2.Name = "Yash";
    Test t = new Test();
    t.list = new ArrayList();
    t.list.Add(e1);
    t.list.Add(e2);
    string text = JsonSerializer.Serialize(t);
    Test t2 = new Test();
    t2 = JsonSerializer.Deserialize<Test>(text);
}

当我使用 Newtonsoft 反序列化时,我在数组 List 中看到 JObjects 而不是 Employee 对象。我可以通过创建 ArrayList 转换器使用 Newtonsoft.Json 解决这个问题。

但是,System.text.Json 无法做到这一点。如何使用 System.Text.Json 反序列化此 ArrayList?这是我需要支持的古老代码,每次我反序列化一个 ArrayList 时,我都知道它应该包含哪种对象类型。

【问题讨论】:

  • 我的建议:不要使用ArrayList。如果您需要事物列表,则使用事物列表,例如List&lt;Employee&gt;
  • @DavidG 是的,如果我们要开始一些新的东西,那是最好的方法,但我可以接受我目前所拥有的。不幸的是,由于项目中的各种原因,我无法更改为 List
  • 如果您可以将list 属性转换为泛型而不是ArrayList,那将是理想的。如果没有,您可以在 System.Text.Json 中创建自定义序列化程序。见stackoverflow.com/questions/67622527/…
  • @JackA。 Employee 只是这里的一个例子,但我有很多这样的场景,上面的例子是针对DateTimeOffset 对象的,所以如果我想为ManagerEmployeeAdmin 等对象写这个,我需要创建多个转换器?我能不能创建一个通用转换器,就像我们在这里所做的那样使用 Newtonsoft.Json stackoverflow.com/questions/41564842/…
  • 您的自定义转换器将基于JsonConverter&lt;ArrayList&gt;,因此您可以在内部检查项目类型。

标签: c# .net-core serialization deserialization system.text.json


【解决方案1】:

如果您事先知道ArrayList 应该包含某种类型的项目,您可以轻松地创建一个JsonConverter&lt;ArrayList&gt; 来序列化和反序列化ArrayList,如下所示:

public class KnownItemTypeArrayListConverter<TItem> : JsonConverter<ArrayList>
{
    public override ArrayList Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
        new ArrayList(JsonSerializer.Deserialize<List<TItem>>(ref reader, options));
        
    public override void Write(Utf8JsonWriter writer, ArrayList value, JsonSerializerOptions options) =>
        JsonSerializer.Serialize(writer, value.Cast<TItem>(), options);
}

然后您可以使用它来序列化和反序列化您的Test 模型,如下所示:

var e1 = new Employee { MyProperty = 1, Name = "Yash", };
var e2 = new Employee { MyProperty = 1, Name = "Yash", };
var t = new Test { list = new ArrayList { e1, e2 }, };

var options = new JsonSerializerOptions
{
    Converters = { new KnownItemTypeArrayListConverter<Employee>() },
};

var text = JsonSerializer.Serialize(t, options);

var t2 = JsonSerializer.Deserialize<Test>(text, options);

演示小提琴 #1 here.

或者,您可以使用 JsonConverterAttribute 将转换器应用于您的模型:

public class Test
{
    public int MyProperty { get; set; }  
    [System.Text.Json.Serialization.JsonConverter(typeof(KnownItemTypeArrayListConverter<Employee>))]
    public ArrayList list { get; set; }
}

(我使用完全限定类型名称以避免与 Newtonsoft 的 JsonConverterAttribute 混淆。)

演示小提琴#2 here.

话虽如此,不推荐使用ArrayList。来自docs

我们不建议您将ArrayList 类用于新开发。相反,我们建议您使用通用的 List&lt;T&gt; 类。

您可以考虑升级旧代码以使用以下模型:

public class Test
{
    public int MyProperty { get; set; }            
    public List<Employee> list { get; set; }
}

【讨论】:

  • 感谢 sn-p @dbc,我尝试创建此转换器,但一个小错误导致运行时异常,再次感谢!!
猜你喜欢
  • 2020-04-06
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 2014-10-26
  • 2020-02-19
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
相关资源
最近更新 更多