【问题标题】:C# Converting Json List to List objects using JsonConverterC# 使用 JsonConverter 将 Json List 转换为 List 对象
【发布时间】:2020-11-09 07:12:38
【问题描述】:

我正在尝试将 Json 中的列表(使用 Newtonsoft.json)转换为自定义的“元素”结构,其中我将有许多类,其中都有一个名为“元素”的属性,但是一些任意类型。

下面代码中使用的一个例子是这个json:

{ 
   "List_A": [1, 2], 
   "List_B": ["Hello", "World"] 
}

在第一个属性“List_A”中,需要将数字转换为 AΞElement 类,该类具有 int 类型的属性 Element。

在第二个属性“List_B”中,需要将这些字符串转换成不同的类BΞElement。

下面是工作代码,我试图填写我创建的 ListConverter 类的 ReadJson 函数,即 JsonConverter。我正在尝试弄清楚如何从序列化程序中读取内容,并创建自己的自定义对象。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;


namespace ConsoleApp1
{
  class Program
  {
    [DataContract]
    public class AΞElement
    {
      [DataMember]
      int _Element;

      public int Element
      {
        get => _Element;
        set => _Element = value;
      }
    }

    [DataContract]
    public class BΞElement
    {
      [DataMember]
      string _Name;

      public string Element
      {
        get => _Name;
        set => _Name = value;
      }
    }

    [DataContract]
    public class C
    {
      [DataMember]
      List<AΞElement> List_A { get; set; } = new List<AΞElement>();

      [DataMember]
      List<BΞElement> List_B { get; set; } = new List<BΞElement>();
    }

    static void Main(string[] args)
    {
      var json = "{ \"List_A\": [1, 2], \"List_B\": [\"Hello\", \"World\"] }";

      var c = JsonConvert.DeserializeObject<C>(json, new JsonSerializerSettings()
      {
        Converters = new List<JsonConverter> { new ListConverter() }
      });
    }

    public class ListConverter : JsonConverter
    {
      public override bool CanConvert(Type objectType)
      {
        return typeof(IList).IsAssignableFrom(objectType);
      }

      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
      {
        if (existingValue != null)
        {
          var list = (IList)existingValue;
          list.Clear();
        }

        var elementType = existingValue.GetType().GetGenericArguments()[0];

        if (elementType.Name.EndsWith("ΞElement"))
        {
          /// What do I put here??
        }
        else
        {
          serializer.Populate(reader, existingValue);
        }

        return existingValue;
      }

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

注意:我必须保持ΞElement和json的类结构相同。

【问题讨论】:

  • Ξ 是用于命名的有效字符吗?
  • 是的。上面的代码是完全可编译的,并且可以运行。测试一下
  • 尽管使用该字符只是手头问题的一个小细节,只要有一些关键方法来识别我正在处理的这些类。
  • 这是一个奇怪的设计。为什么不简单地使用List&lt;int&gt;List&lt;string&gt;?对我来说似乎是XYProblem。您要解决的问题是什么?
  • 我别无选择,我必须这样做

标签: c# json.net deserialization


【解决方案1】:

如果我理解正确,我会得出这样的解决方案:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (existingValue != null)
    {
        var list = (IList)existingValue;
        list.Clear();
    }

    var elementType = existingValue.GetType().GetGenericArguments()[0];

    if (elementType.Name.EndsWith("ΞElement"))
    {
        var list = (IList)existingValue;

        if (elementType.Name.EndsWith("AΞElement"))
        {
            while (reader.Read() && reader.Value != null)
            {
                list.Add(new AΞElement
                {
                    Element = Convert.ToInt32(reader.Value)
                });
            }
        }
        else if (elementType.Name.EndsWith("BΞElement"))
        {
            while (reader.Read() && reader.Value != null)
            {
                list.Add(new BΞElement
                {
                    Element = (string)reader.Value
                });
            }
        }
    }
    else
    {
        serializer.Populate(reader, existingValue);
    }

    return existingValue;
}

基本上,我正在检查 AΞElement 和 BΞElement 的类型,从 JsonReader 读取并将数组中的值一一添加到相关列表中,直到没有更多要读取的标记。

【讨论】:

  • 啊,这就是你从读者那里反序列化的方式。谢谢。我早上起床后看看
猜你喜欢
  • 2021-03-28
  • 1970-01-01
  • 2017-03-27
  • 1970-01-01
  • 2017-07-04
  • 2021-09-27
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多