Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I skip default JavaScript array serialization for IEnumerable types in Json.Net?

Some custom types that implement IEnumerable don't necessarily have backing collections. They could be generated dynamically, for example using 'yield' or LINQ. Here is an example:

public class SOJsonExample
{
    public class MyCustomEnumerable : IEnumerable<KeyValuePair<int,float>>
    {
        public List<int> Keys { get; set; }
        public List<float> Values { get; set; }

        public MyCustomEnumerable()
        {
            Keys = new List<int> { 1, 2, 3 };
            Values = new List<float> { 0.1f, 0.2f, 0.3f };
        }

        public IEnumerator<KeyValuePair<int, float>> GetEnumerator()
        {
            var kvps =
                from key in Keys
                from value in Values
                select new KeyValuePair<int, float>(key, value);

            return kvps.GetEnumerator();
        }

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

I have discovered that the default serialization by Json.NET is to enumerate each value and store the values in a JavaScript array (which I don't want). The default deserializer will then fail to deserialize the collection as it can't be populated. In these cases, I'd instead want Json.NET to skip the default JavaScript array serialization, and just store the members of the class.

All I want is my keys and values - is there any shortcut way to do this, or do I have to implement my own custom serializer?

Checked this and this, neither of which are exactly my question. Scanned the documentation as well, but didn't find what I was looking for (perhaps I looked in the wrong place).

(Edit #1 - improved clarity)

(Edit #2 - answered my own question...see below)

like image 864
lightw8 Avatar asked Feb 22 '13 23:02

lightw8


1 Answers

Answered my own question - see the excellent documentation on IEnumerable, Lists, and Arrays:

.NET lists (types that inherit from IEnumerable) and .NET arrays are converted to JSON arrays. Because JSON arrays only support a range of values and not properties, any additional properties and fields declared on .NET collections are not serialized. In situations where a JSON array is not wanted the JsonObjectAttribute can be placed on a .NET type that implements IEnumerable to force the type to be serialized as a JSON object instead.

So, for my example:

[JsonObject]
public class MyCustomEnumerable : IEnumerable<KeyValuePair<int,float>>
{
    ...
}
like image 135
lightw8 Avatar answered Oct 10 '22 19:10

lightw8