2

I have a class that inherits from List<T> and add one more class property

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

    private DrivenList() { }

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

When JSON serializing the object using Newtonsoft.Json, I get only the list item. ( [1,2,3] )

Any ideas how to add the Name property to the results?

Solved: by adding this attribute to the list

[JsonObject(MemberSerialization = MemberSerialization.Fields)]
public class DrivenList : List<int>
Moshe Stone
  • 95
  • 1
  • 8

4 Answers4

2

As far as I know with Newtonsoft all you can do is something like this:

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

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

    private DrivenList() { }

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

But this will add you unwanted (maybe) fields.

Personally I will do composition instead of inheritance:

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

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

    private DrivenList() { }

    public DrivenList(string name) { this.Name = name; }
}
meJustAndrew
  • 4,755
  • 4
  • 40
  • 63
Ioana Stoian
  • 106
  • 9
1

An alternative solution could be to delegate the implementation of IList to your own property. Then you can use the DataContractSerializer. The upside of this is that all the existing C#-code (and all your tests) will still be intact, and no custom logic is needed for serializing it.

If that's not an option and you really want to use NewtonSoft, then you should take a look at this answer, and create your own JsonConverter.

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

The problem is the following: when an object implements IEnumerable, JSON.net identifies it as an array of values and serializes it following the array Json syntax (that does not include properties)

Here's an example that use 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;
    }
}

And the new implementation of your class.

[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
}

And an example usage:

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

var json = JsonHelper.JsonSerializer(list);

Output:

{"Items":[1,3,5],"Name":"foo"}
Community
  • 1
  • 1
smoksnes
  • 9,330
  • 3
  • 41
  • 57
  • Care to elaborate the downvote? The example works and the initial OP didn't mention NewtonSoft as a requirement. – smoksnes Aug 23 '16 at 06:02
0

What .NET version are you using and what serializer? If you are using the standard serializer, then adding [DataMember] annotations would be the answer.
https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx

But I would suggest to use Json.NET http://www.newtonsoft.com/json

Update:

I would suggest not to directly inherit to 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; }
}

Output:

{"Items":[1,2],"Name":"Ragnarok"}
Fritz
  • 31
  • 6
0

Apply the DataContract attribute for the class and DataMember attribute for the properties.

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

    private DrivenList() { }

    public DrivenList(string name) { this.Nname = name; }
}
Aniruddha Varma
  • 1,393
  • 1
  • 19
  • 32