Serializing Json.Net IEnumerable with TypeNameHandling = auto

According to the Json.Net documentation, all types IEnumerablemust be serialized as a json array.

So, I expect the following class:

public class MyClass
{
    public IEnumerable<string> Values { get; set; }
}

for serialization:

{
    "Values": []
}

The problem is that when I use TypeNameHandling=Auto, I get:

{
    "Values": {
        "$type": "System.String[], mscorlib",
        "$values": []
    }
}

I need TypeNameHandling=Autofor other properties, but I expect IEnumerableto use default serialization. Other types (e.g. IList) work as expected.

Is this a mistake or am I missing something?

Here is the full code to reproduce the problem:

    [Test]
    public void Newtonsoft_serialize_list_and_enumerable()
    {
        var target = new Newtonsoft.Json.JsonSerializer
        {
            TypeNameHandling = TypeNameHandling.Auto
        };

        var myEvent = new MyClass
        {
            Values = new string[0]
        };

        var builder = new StringWriter();
        target.Serialize(builder, myEvent);
        var json = JObject.Parse(builder.ToString());

        Assert.AreEqual(JTokenType.Array, json["Values"].Type);
    }

    public class MyClass
    {
        public IEnumerable<string> Values { get; set; }
    }

I am using Newtonsoft 7.0.1.

UPDATE : Here is another test using more types:

    [Test]
    public void Newtonsoft_serialize_list_and_enumerable()
    {
        var target = new Newtonsoft.Json.JsonSerializer
        {
            TypeNameHandling = TypeNameHandling.Auto
        };

        var myEvent = new MyClass
        {
            Values1 = new string[0],
            Values2 = new List<string>(),
            Values3 = new string[0],
            Values4 = new List<string>(),
            Values5 = new string[0]
        };

        var builder = new StringWriter();
        target.Serialize(builder, myEvent);
        var json = builder.ToString();
    }

    public class MyClass
    {
        public IEnumerable<string> Values1 { get; set; }
        public IEnumerable<string> Values2 { get; set; }
        public IList<string> Values3 { get; set; }
        public IList<string> Values4 { get; set; }
        public string[] Values5 { get; set; }
    }

And these are the results:

{
    "Values1": {
        "$type": "System.String[], mscorlib",
        "$values": []
    },
    "Values2": [],
    "Values3": {
        "$type": "System.String[], mscorlib",
        "$values": []
    },
    "Values4": [],
    "Values5": []
}

Again I don't understand why I get different results depending on the combination.

+4
2

Json.Net IEnumerable IList List. Array, - , Json.Net $type, , . IEnumerable.

List<string>:

var myEvent = new MyClass
{
    Values = new List<string>(),
};

:

public class MyClass
{
   public IEnumerable<string> Values { get; set; }
}    

( ):

{"Values":["hello"]}

, , Json.Net $type;

:

string[] Values { get; set; } = new string[0]; // not needed
IEnumerable<string> Values { get; set; } = new string[0]; //$type needed
IEnumerable<string> Values { get; set; } = new Stack<string>(); //$type needed
IEnumerable<string> Values { get; set; } = new List<string>; // not needed
List<string> Values { get; set; } = new List<string>; // not needed

ObservableCollection<string> Values { get; set; } = 
    new ObservableCollection<string>(); // not needed
+3

, . TypeNameHandling . , , , , TypeNameHandling.Auto:

[JsonProperty(TypeNameHandling = TypeNameHandling.None)]

:

    public class MyClass
    {
        // Indicate the property not to apply any type handling
        [JsonProperty(TypeNameHandling=TypeNameHandling.None)]
        public IList<string> Values { get; set; }

        public string Name { get; set; }
    }

TypeNameHandling, .

+2

Source: https://habr.com/ru/post/1623322/


All Articles