如何使用 Json.NET 序列化和反序列化数组的 ArrayList

2023-12-04

我需要在应用程序中使用 JSON.NET 将对象序列化/反序列化为 json。 Object 具有 ArrayList 属性类型,其中包含字符串数组。为了模拟它,我编写了以下单元测试;

public class JsonTests
{
    public class MyTestClass
    {
        public ArrayList Items { get; private set; }

        public MyTestClass()
        {
            this.Items = new ArrayList();
        }
    }
    [Fact]
    public void JsonConvert_Should_Serialize_ArrayList_And_Deserialize_Successfully()
    {
        MyTestClass myObject = new MyTestClass();
        myObject.Items.Add(new string[] { "Test1", "Test2" });
        string jsonResult = JsonConvert.SerializeObject(myObject);            
        MyTestClass tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult);
         //(tempMyObject.Items[0] as string[]) casts to null therefore it throws exception
        Assert.Equal((myObject.Items[0] as string[])[0], (tempMyObject.Items[0] as string[])[0]);
    } 
}

它在序列化过程中不会抛出任何异常。但是,它无法正确反序列化 ArrayList。

我的问题是,如何将其反序列化回字符串数组的 ArrayList ?

Update:另外,我无法更改类定义。该类是在我无法编辑该类的程序集中实现的。


ArrayList是一个非泛型、无类型的集合,因此您需要告知 Json.NET 项目的预期类型。一种方法是使用custom JsonConverter为了ArrayList:

public class ArrayListConverter<TItem> : JsonConverter
{
    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var list = serializer.Deserialize<List<TItem>>(reader);
        var arrayList = existingValue as ArrayList ?? new ArrayList(list.Count);
        arrayList.AddRange(list);
        return arrayList;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ArrayList);
    }
}

然后将转换器应用到该类,如下所示:

public class MyTestClass
{
    [JsonConverter(typeof(ArrayListConverter<string []>))]
    public ArrayList Items { get; private set; }

    public MyTestClass()
    {
        this.Items = new ArrayList();
    }
}

Sample fiddle.

如果类无法修改,并且您想要所有实例 of ArrayList在您的对象图中将其项目反序列化为string [],您可以将转换器添加到JsonSerializerSettings.Converters而不是将其添加到类型中:

var tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult,
                                                              new JsonSerializerSettings { Converters = { new ArrayListConverter<string []>() } });

Sample 小提琴#2.

最后,如果类无法修改并且您只想要特定的ArrayList Items里面的财产MyTestClass将其项目反序列化为string [],您将需要创建一个自定义转换器MyTestClass。您可以使用以下模式自定义反序列化器仅适用于 json.NET 的某些字段自定义反序列化ArrayList属性,同时使用默认反序列化填充其余部分:

public class MyTestClassConverter : JsonConverter
{
    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var root = existingValue as MyTestClass ?? (MyTestClass)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
        var jsonObject = JObject.Load(reader);

        var jsonItems = jsonObject["Items"].RemoveFromLowestPossibleParent();
        if (jsonItems != null && jsonItems.Type != JTokenType.Null)
        {
            root.Items.AddRange(jsonItems.ToObject<List<string []>>());
        }
        // Populate the remaining standard properties
        using (var subReader = jsonObject.CreateReader())
        {
            serializer.Populate(subReader, root);
        }
        return root;
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(MyTestClass).IsAssignableFrom(objectType);
    }
}

public static class JsonExtensions
{
    public static JToken RemoveFromLowestPossibleParent(this JToken node)
    {
        if (node == null)
            return null;
        var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault();
        if (contained != null)
            contained.Remove();
        // Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
        if (node.Parent is JProperty)
            ((JProperty)node.Parent).Value = null;
        return node;
    }
}

然后按如下方式使用它:

var tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult,
                                                              new JsonSerializerSettings { Converters = { new MyTestClassConverter() } });

Sample 小提琴#3.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Json.NET 序列化和反序列化数组的 ArrayList 的相关文章

随机推荐

  • IllegalArgumentException:从视图加载位图时宽度和高度必须 > 0

    我正在尝试使用 ImageViewTouch 这是一个支持捏缩放的库 我可以使用 Canvas 在图像上绘图 但是当我缩放图像时 绘图会消失 为此 我尝试将视图转换为位图并为同一视图设置 theImageBitmap 这是代码 mImage
  • Chrome 自动填充会导致文本字段标签和值的文本框发生冲突

    在 React 中 自动完成 Chrome 值不会立即触发 onChange 事件 因此 在页面初始加载期间 它会导致 MUI TextField Label 和实际值发生冲突 我该如何解决这个问题 尝试了多种方法 InputLabelPr
  • 在元素中创建响应式对角线

    不确定这是否可行 但是如何创建一条从元素左上角到右下角的 1px 对角线 无论该元素的宽度和 或高度如何 您可以通过多种方式做到这一点 1 背景图片 1 1 SVG 您可以直接创建 svg 作为内联代码并使用它来绘制线条 使用它你可以实现漂
  • .NET 反射 - 从实例属性获取声明类类型

    是否可以从属性实例获取类的类型 我尝试了以下方法 var model new MyModel SomeValueForMyProperty Type declaringType model MyProperty GetType Declar
  • 将单词添加到一行的最后一个单词之前

    我想在一行的最后一个单词前面添加一个目录名称 该行具有以下格式 100644 bfadfab6f98b8fa1e9989fe16b2bf0fb13ffd39e 0 IoneFile where I表示一个tab and 表示行尾 该行是由生
  • 如何在 Typescript Enum 中查找具有值的键?

    我想搜索一个具有值的枚举 并获取它的键 这就是我现在所拥有的 private find value MyEnum string for const key in MyEnum if value MyEnum key return key r
  • 如何在 java 中将节点附加到现有 XML 文件

    public static void addALLToXML Collection
  • return 语句上的 Perl 引用和取消引用

    我正在学习 perl 并且有一个与参考文献相关的问题 我正在研究 get id 函数 如果我回来 self gt id 我将得到两个无法运行的数组地址 c 以我的理解 a是参考和 a 是数组并且 a 0 会返回值0吗 这是我第一次在 sta
  • bitParity - 查找整数中的奇数位

    我必须创建一个函数bitParity int x 接受一个整数并返回1如果有奇数个0的位形式为x and 0否则 Ex bitParity 5 0 bitParity 7 1 然而 这很困难 因为我只能使用位运算符来解决这个问题 lt lt
  • 我想在 Rstudio 中更改 --max-ppsize

    我读过了如何在 R 中设置最大 ppsize 我也有同样的问题 我目前在 Rstudio 工作 我需要将 max ppsize 设置为更大的值 这是我的方法 gt setwd C Program Files R R 3 3 1 bin gt
  • Emacs 用增量序列替换正则表达式

    我正在尝试找出一种方法 将文本文件中的字符串替换为增量超过 1 的数字 我正在尝试将以下几行转为这样 result A in S1 S2 txt result A in S1 S2 txt result A in S1 S2 txt res
  • php mPDF,无法设置字体系列和字体大小

    好吧 在花了这么多时间阅读他们的文档和我的测试之后 我决定向 SO 社区寻求帮助 我使用 mPDF 从 HTML 生成 pdf 图书馆工作正常 pdf 已生成等 但我无法根据需要设置字体系列和字体大小 我尝试过的代码 mpdf new mP
  • shell编程中的“导出”有什么作用? [复制]

    这个问题在这里已经有答案了 据我所知 无论前面是否有 export 变量赋值都是相同的 这是为了什么 导出的变量如 HOME and PATH可供 shell 运行的其他程序使用 继承 并将它们导出为环境变量 以及这些其他程序运行的程序等
  • 使用当前连接从 sql 存储过程调用 dll 函数

    我可以使用打开的连接从存储过程调用 dll 吗 我有一个从 SQL Server 获取数据的 dll 当我从存储过程调用它时 我不想打开新连接 谢谢 这是一个例子 public class Class1 public static SqlS
  • JavaScript Promise .then() 在事件循环中到底是如何处理的?

    我对如何将以下测试代码放入 JS 事件循环中感到困惑 var p1 new Promise function resolve reject setTimeout function resolve 1 100 var p2 new Promi
  • 用JS从outlook导入联系人

    我需要将 Outlook 中的联系人导入到 Web 应用程序中 我认为用JS可以做到这一点 但我不知道如何做 谁能给我一个解决我的问题的示例代码 您可以使用activex和javascript导出outlook联系人 但需要用户在浏览器中启
  • 如何将H2数据库嵌入到交付给客户端的jar文件中?

    我在嵌入式模式下使用 H2 数据库作为桌面应用程序 当我将应用程序压缩到 jar 文件中时 数据库文件被省略 因此 当我运行 MyApplication jar 时 没有任何效果 将 h2 jar 文件嵌入 包含 连接 MyApplicat
  • 删除 JSON 中的 Null 值并更新 JSON

    我通过使用 Newtonsoft 序列化列表将 JSON 数组作为字符串 如下所示 ID 1 Name somename Class 12 Section null ID null Name somename Class 13 Sectio
  • MapView 上的 java.util.ConcurrentModificationException

    fellas 很多天以来我都面临着非常奇怪的问题 我正在尝试经常更新覆盖 因此 有时当我触摸地图时 我会收到 java util ConcurrentModificationException 或者有时当地图尝试更新叠加层时 我会收到 ja
  • 如何使用 Json.NET 序列化和反序列化数组的 ArrayList

    我需要在应用程序中使用 JSON NET 将对象序列化 反序列化为 json Object 具有 ArrayList 属性类型 其中包含字符串数组 为了模拟它 我编写了以下单元测试 public class JsonTests public