-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
ValueTuple is not Supported in Aspnet Core 3.1 with default Json. #1519
Comments
/cc @ahsonkhan - feedback about JSON. |
Duplicate of #876? |
This is a duplicate of #876.
Other similar issues: Here's a potential workaround in the mean time using a custom converter: public class ValueTupleFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
Type iTuple = typeToConvert.GetInterface("System.Runtime.CompilerServices.ITuple");
return iTuple != null;
}
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Type[] genericArguments = typeToConvert.GetGenericArguments();
Type converterType = genericArguments.Length switch
{
1 => typeof(ValueTupleConverter<>).MakeGenericType(genericArguments),
2 => typeof(ValueTupleConverter<,>).MakeGenericType(genericArguments),
3 => typeof(ValueTupleConverter<,,>).MakeGenericType(genericArguments),
// And add other cases as needed
_ => throw new NotSupportedException(),
};
return (JsonConverter)Activator.CreateInstance(converterType);
}
}
public class ValueTupleConverter<T1> : JsonConverter<ValueTuple<T1>>
{
public override ValueTuple<T1> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
ValueTuple<T1> result = default;
if (!reader.Read())
{
throw new JsonException();
}
while (reader.TokenType != JsonTokenType.EndObject)
{
if (reader.ValueTextEquals("Item1") && reader.Read())
{
result.Item1 = JsonSerializer.Deserialize<T1>(ref reader, options);
}
else
{
throw new JsonException();
}
reader.Read();
}
return result;
}
public override void Write(Utf8JsonWriter writer, ValueTuple<T1> value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WritePropertyName("Item1");
JsonSerializer.Serialize<T1>(writer, value.Item1, options);
writer.WriteEndObject();
}
}
public class ValueTupleConverter<T1, T2> : JsonConverter<ValueTuple<T1, T2>>
{
public override (T1, T2) Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
(T1, T2) result = default;
if (!reader.Read())
{
throw new JsonException();
}
while (reader.TokenType != JsonTokenType.EndObject)
{
if (reader.ValueTextEquals("Item1") && reader.Read())
{
result.Item1 = JsonSerializer.Deserialize<T1>(ref reader, options);
}
else if (reader.ValueTextEquals("Item2") && reader.Read())
{
result.Item2 = JsonSerializer.Deserialize<T2>(ref reader, options);
}
else
{
throw new JsonException();
}
reader.Read();
}
return result;
}
public override void Write(Utf8JsonWriter writer, (T1, T2) value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WritePropertyName("Item1");
JsonSerializer.Serialize<T1>(writer, value.Item1, options);
writer.WritePropertyName("Item2");
JsonSerializer.Serialize<T2>(writer, value.Item2, options);
writer.WriteEndObject();
}
}
public class ValueTupleConverter<T1, T2, T3> : JsonConverter<ValueTuple<T1, T2, T3>>
{
public override (T1, T2, T3) Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
(T1, T2, T3) result = default;
if (!reader.Read())
{
throw new JsonException();
}
while (reader.TokenType != JsonTokenType.EndObject)
{
if (reader.ValueTextEquals("Item1") && reader.Read())
{
result.Item1 = JsonSerializer.Deserialize<T1>(ref reader, options);
}
else if (reader.ValueTextEquals("Item2") && reader.Read())
{
result.Item2 = JsonSerializer.Deserialize<T2>(ref reader, options);
}
else if (reader.ValueTextEquals("Item3") && reader.Read())
{
result.Item3 = JsonSerializer.Deserialize<T3>(ref reader, options);
}
else
{
throw new JsonException();
}
reader.Read();
}
return result;
}
public override void Write(Utf8JsonWriter writer, (T1, T2, T3) value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WritePropertyName("Item1");
JsonSerializer.Serialize<T1>(writer, value.Item1, options);
writer.WritePropertyName("Item2");
JsonSerializer.Serialize<T2>(writer, value.Item2, options);
writer.WritePropertyName("Item3");
JsonSerializer.Serialize<T3>(writer, value.Item3, options);
writer.WriteEndObject();
}
}
public class WeatherForecastValueTuple
{
public ValueTuple<string> Temp { get; set; }
public (int x, int y) Location { get; set; }
public (int a, Poco b, ValueTuple<string> c) Thruple { get; set; }
}
public class Poco
{
public int Alpha { get; set; }
public (List<int>, string) Beta { get; set; }
}
private static void SupportValueTuple()
{
var objectWithValueTuple = new WeatherForecastValueTuple
{
Location = (3, 7),
Temp = new ValueTuple<string>("FOO"),
Thruple = (
8,
new Poco
{
Alpha = 9,
Beta = (new List<int>() { -1, 0, -1 }, "a list")
},
new ValueTuple<string>("Bar"))
};
var options = new JsonSerializerOptions();
options.Converters.Add(new ValueTupleFactory());
string jsonString = JsonSerializer.Serialize(objectWithValueTuple, options);
Console.WriteLine(jsonString);
WeatherForecastValueTuple roundTrip = JsonSerializer.Deserialize<WeatherForecastValueTuple>(jsonString, options);
Assert.Equal((3, 7), roundTrip.Location);
Assert.Equal(new ValueTuple<string>("FOO"), roundTrip.Temp);
} Within Aspnet you can register it as follows: services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new ValueTupleFactory());
}); |
actual output: {}.
expected output:{"item1":1,"item2":2,"item3":3}
The text was updated successfully, but these errors were encountered: