-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide option for the serializer to treat IEnumerables like objects with members #1808
Comments
I don't think so at this time. I believe if the object we are serializing at the top level is an enumerable, we ignore other top level attributes all the time. Adding an optional parameter for this may be nice; serializing a List would probably include Count and Capacity. It also brings the question if the parameter applies to enumerable serialization at all levels or just top level (For all serialized Lists we'd get the Count and Capacity also). The expected output you put is what I would imagine this situation done through composition.
|
@vitalie-ucommerce, is there any reason you couldn't wrap the |
@ahsonkhan that would be easiest, of course. But it's not what the requirements are, we need like a
but also like this:
|
|
From myself in #30855:
I'll rename this issue as well. |
Is there a workaround for this since it's not yet supported out of the box? |
Have recently bumped up against this limitation had to remove the interfaces to get our custom collections to work. Luckily foreach only requires the presence of the enumerator method. From the looks of it, we can't disable this behaviour or even replace the enumerable converter. Further comment would be welcome. |
The workaround here is to write a custom converter for the type. Here's an example using the using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
public class Program
{
public static void Main()
{
var my = new MyEnumerable();
my.Stuff = new List<string> { "one", "two" };
my.Doing = 3;
var options = new JsonSerializerOptions { Converters = { new MyEnumerableConverter() } };
string json = JsonSerializer.Serialize(my, options);
Console.WriteLine(json); // {"Doing":3,"Stuff":["one","two"]}
my = JsonSerializer.Deserialize<MyEnumerable>(json, options);
Console.WriteLine(my.Doing); // 3
Console.WriteLine(my.Stuff[0]); // one
Console.WriteLine(my.Stuff[1]); // two
}
public class MyEnumerable : IEnumerable<string>
{
public int Doing { get; set; }
public IList<string> Stuff { get; set; }
public IEnumerator<string> GetEnumerator()
{
return Stuff.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class MyEnumerableConverter : JsonConverter<MyEnumerable>
{
public override MyEnumerable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// By default, serializer handles null deserialization for reference types.
Debug.Assert(reader.TokenType != JsonTokenType.Null);
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}
var obj = new MyEnumerable();
do
{
reader.Read();
if (reader.TokenType == JsonTokenType.PropertyName)
{
string propName = reader.GetString();
reader.Read();
if (propName == "Doing")
{
obj.Doing = reader.GetInt32();
}
else if (propName == "Stuff")
{
obj.Stuff = JsonSerializer.Deserialize<IList<string>>(ref reader, options);
}
else
{
reader.Skip();
}
}
else if (reader.TokenType == JsonTokenType.EndObject)
{
break;
}
} while (true);
return obj;
}
public override void Write(Utf8JsonWriter writer, MyEnumerable value, JsonSerializerOptions options)
{
// By default, serializer handles null serialization.
Debug.Assert(value != null);
writer.WriteStartObject();
writer.WriteNumber("Doing", value.Doing);
writer.WritePropertyName("Stuff");
JsonSerializer.Serialize(writer, value.Stuff, options);
writer.WriteEndObject();
}
}
} |
@layomia , is the workaround temporary or permanent (as in, there are no plans to support it out of the box)? This is blocking our migration from newtonsoft as well |
@rvarna - we could support this out of the box in the future. This is not planned for .NET 6.0 since there is a workaround and the community demand for this is low compared to other features. |
One possible workaround is to simply expose |
Closing in favor of #63791. |
If I have a similar class:
The result of the serialization will be just the values of
Stuff
.Fx.:
the result is:
["one","two"]
.The
Doing
member is ingored. So the expected result would be:{"Doing":3,"Stuff":["one","two"]}
.In Newtonsoft.JSON I can use
[JsonObject]
attribute, to enforce the serialization of all the members.Is there something similar in
System.Text.Json
? And if not, is there plan to implement it?The text was updated successfully, but these errors were encountered: