【问题标题】:JSON serialization with class inherited from List<T>类继承自 List<T> 的 JSON 序列化
【发布时间】:2016-08-23 04:55:13
【问题描述】:

我有一个继承自 List&lt;T&gt; 的类并添加了一个类属性

public class DrivenList : List<int>
{
    public string Name {get;set;}

    private DrivenList() { }

    public DrivenList(string name) { this.Nname = name; }
}

当 JSON 使用 Newtonsoft.Json 序列化对象时,我只得到列表项。 ([1,2,3])

知道如何将Name 属性添加到结果中吗?

已解决:通过将此属性添加到列表中

[JsonObject(MemberSerialization = MemberSerialization.Fields)]
public class DrivenList : List<int>

【问题讨论】:

标签: c# json


【解决方案1】:

据我所知,使用 Newtonsoft,您所能做的就是这样:

[JsonObject(MemberSerialization = MemberSerialization.Fields)]
public class DrivenList : List<int>
{

    [JsonProperty]
    public string Name { get; set; }

    private DrivenList() { }

    public DrivenList(string name) { this.Name = name; }
}

但这会给你添加不需要的(可能)字段。

我个人会做组合而不是继承:

public class DrivenList
{
    public string Name { get; set; }

    public List<int> Items { get; set; }

    private DrivenList() { }

    public DrivenList(string name) { this.Name = name; }
}

【讨论】:

  • 非常感谢洛安娜!添加 JsonObjectAttribute 解决了我的问题
【解决方案2】:

另一种解决方案是将IList 的实现委托给您自己的财产。然后你可以使用DataContractSerializer。这样做的好处是所有现有的 C# 代码(以及您的所有测试)仍然完好无损,并且不需要自定义逻辑来对其进行序列化。

如果这不是一个选项,并且您真的想使用 NewtonSoft,那么您应该看看这个答案,并创建您自己的 JsonConverter

How to serialize/deserialize a custom collection with additional properties using Json.Net

问题如下:当一个对象实现 IEnumerable 时, JSON.net 将其识别为值数组并将其序列化 跟随数组Json syntax(不包括属性)

这是一个使用DataContractSerializer的例子:

JsonHelper from CodeProject

public class JsonHelper
{
    /// <summary>
    /// JSON Serialization
    /// </summary>
    public static string JsonSerializer<T>(T t)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        MemoryStream ms = new MemoryStream();
        ser.WriteObject(ms, t);
        string jsonString = Encoding.UTF8.GetString(ms.ToArray());
        ms.Close();
        return jsonString;
    }

    /// <summary>
    /// JSON Deserialization
    /// </summary>
    public static T JsonDeserialize<T>(string jsonString)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
        T obj = (T)ser.ReadObject(ms);
        return obj;
    }
}

还有你的类的新实现。

[DataContract]
public class DrivenList : IList<int>
{

    [DataMember]
    public List<int> Items = new List<int>();

    [DataMember]
    public string Name { get; set; }

    private DrivenList() { }

    public DrivenList(string name) { this.Name = name; }


    #region Implementation of IList

    public IEnumerator<int> GetEnumerator()
    {
        return Items.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable)Items).GetEnumerator();
    }

    public void Add(int item)
    {
        Items.Add(item);
    }

    public void Clear()
    {
        Items.Clear();
    }

    public bool Contains(int item)
    {
        return Items.Contains(item);
    }

    public void CopyTo(int[] array, int arrayIndex)
    {
        Items.CopyTo(array, arrayIndex);
    }

    public bool Remove(int item)
    {
        return Items.Remove(item);
    }

    public int Count
    {
        get { return Items.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public int IndexOf(int item)
    {
        return Items.IndexOf(item);
    }

    public void Insert(int index, int item)
    {
        Items.Insert(index, item);
    }

    public void RemoveAt(int index)
    {
        Items.RemoveAt(index);
    }

    public int this[int index]
    {
        get { return Items[index]; }
        set { Items[index] = value; }
    }

    #endregion
}

还有一个用法示例:

var list = new DrivenList("foo");
list.Add(1);
list.Add(3);
list.Add(5);

var json = JsonHelper.JsonSerializer(list);

输出:

{"Items":[1,3,5],"Name":"foo"}

【讨论】:

  • 想详细说明否决票?该示例有效,并且最初的 OP 没有提到 NewtonSoft 作为要求。
【解决方案3】:

为类应用DataContract 属性,为属性应用DataMember 属性。

[DataContract]
public class DrivenList : List<int>
{
    [DataMember]
    public string Name {get;set;}

    private DrivenList() { }

    public DrivenList(string name) { this.Nname = name; }
}

【讨论】:

  • 谢谢@AlekseyL :)。 ...知道它是如何工作的吗?
  • 您需要一个自定义的JsonConverter 来完成这项工作,因为NewtonSoft 简单地将DrivenList 视为IEnumerable 并将其呈现为一个数组。
  • @smoksnes 我明白了,谢谢。我刚刚对您的回答投了赞成票,不知道为什么它被否决了。
【解决方案4】:

您使用的是什么 .NET 版本以及什么序列化程序? 如果您使用的是标准序列化程序,那么添加 [DataMember] 注释就是答案。
https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx

但我建议使用 Json.NET http://www.newtonsoft.com/json

更新:

我建议不要直接继承到List

class Program
{
    static void Main(string[] args)
    {
        var list = new Driven("Ragnarok");
        list.Items.Add(1);
        list.Items.Add(2);

        string json = JsonConvert.SerializeObject(list);
        Console.WriteLine(json);
        Console.ReadKey();
    }
}

public class Driven
{
    public Driven(string name)
    {
        this.Name = name;
    }
    public List<int> Items { get; set; } = new List<int>();
    public string Name { get; set; }
}

输出:

{"Items":[1,2],"Name":"Ragnarok"}

【讨论】:

  • 我使用 Newtonsoft.Json,.net FW 4.5
猜你喜欢
  • 2023-03-30
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多