如何添加两个具有相同名称的属性,以便我们能够反序列化两种不同的JSON格式?

时间:2016-09-25 07:58:27

标签: c# json interface javascriptserializer

我必须解析一个JSON元素;有时候它会是一个单独的对象,有时候是一个对象数组。我没有为每个场景创建一个单独的类,而是想在一个类中创建它。

 public name name { get; set; }
 public name[] name { get; set; }

我在Stack Overflow中提到了类似的问题。在某些情况下,使用接口来解决它。

public class name : INames, INameLists
{
    nameval INames.name { get; set; }
    nameval[] INameLists.name { get; set; }
}

但这不适合我。 JSON元素没有解析,我得到一个例外。

我希望条件能够在存在元素数组时,它必须解析为数组,否则解析为单个对象。

请帮助解决此问题。我不认为这是一个重复的问题。如果是的话,请告诉我。

1 个答案:

答案 0 :(得分:2)

您可以通过使用自定义JavaScriptConverter类来读取JSON元素并决定使用它来解决此问题:即,如果名称是数组,则在类上填充一个属性,或者如果它&# 39;单个对象,填充不同的属性。 当然,您无法定义一个具有两个同名成员的类,而不像您在问题中显示的那样在其上放置显式接口,因此属性必须具有不同的名称。

我可能会定义类似这样的类:

public class NameObject
{
    public string[] Names { get; set; }
    public string Name
    {
        get { return (Names != null && Names.Length > 0) ? Names[0] : null; }
        set { Names = (value != null) ? new string[] { value } : null; }
    }
}

您可以在此处看到Names属性始终包含实际数据,而Name属性只是在只有一个名称时的便利。

以下是我编写转换器的方法:

public class NameObjectConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(NameObject) }; }
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        NameObject nameObj = new NameObject();
        string singleName = GetValue<string>(dictionary, "name");
        if (singleName != null)
        {
            nameObj.Name = singleName;
        }
        else
        {
            ArrayList arrayList = GetValue<ArrayList>(dictionary, "name");
            nameObj.Names = (arrayList != null) ? arrayList.Cast<string>().ToArray() : null;
        }
        return nameObj;
    }

    private T GetValue<T>(IDictionary<string, object> dict, string key)
    {
        object value = null;
        dict.TryGetValue(key, out value);
        return value != null && typeof(T).IsAssignableFrom(value.GetType()) ? (T)value : default(T);
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        NameObject nameObj = (NameObject)obj;
        Dictionary<string, object> dict = new Dictionary<string, object>();
        if (nameObj.Names != null && nameObj.Names.Length == 1)
        {
            dict.Add("name", nameObj.Name);
        }
        else
        {
            dict.Add("name", nameObj.Names);
        }
        return dict;
    }
}

要使用转换器,您必须使用JavaScriptSerializer

进行注册
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new List<JavaScriptConverter> { new NameObjectConverter() });

这是一个演示,显示了两种JSON格式的转换器。 (我不得不在这里编写一些假的JSON,因为你没有提到你的问题中实际的JSON是什么样的。)

public class Program
{
    public static void Main(string[] args)
    {
        string json = @"
        {
          ""doctor"": {
            ""name"": ""Dr. Herbert Q. Cunningham III""
          },
          ""patients"": {
            ""name"": [
              ""Joe Schmoe"",
              ""John Doe"",
              ""Steve Smith""
            ]
          }
        }";

        var serializer = new JavaScriptSerializer();
        serializer.RegisterConverters(new List<JavaScriptConverter> { new NameObjectConverter() });
        MedicalData data = serializer.Deserialize<MedicalData>(json);
        Console.WriteLine("Doctor's name: " + data.Doctor.Name);
        Console.WriteLine("Patients' names: ");
        foreach (string name in data.Patients.Names)
        {
            Console.WriteLine("  " + name);
        }
    }
}

public class MedicalData
{
    public NameObject Doctor { get; set; }
    public NameObject Patients { get; set; }
}

输出:

Doctor's name: Dr. Herbert Q. Cunningham III
Patients' names:
  Joe Schmoe
  John Doe
  Steve Smith