// we want a static field and this is not static
(BindingFlags.Static & bindingAttr) != 0 && !fieldSymbol.IsStatic ||
// we want an instance field and this is static or a constant
- (BindingFlags.Instance & bindingAttr) != 0 && (fieldSymbol.IsStatic || fieldSymbol.IsConst))
+ (BindingFlags.Instance & bindingAttr) != 0 && (fieldSymbol.IsStatic || fieldSymbol.IsConst) ||
+ // symbol represents an explicitly named tuple element
+ fieldSymbol.IsExplicitlyNamedTupleElement)
{
continue;
}
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
public interface ITestContext
{
public JsonSourceGenerationMode JsonSourceGenerationMode { get; }
+ public bool IsIncludeFieldsEnabled => GetType().GetCustomAttribute<JsonSourceGenerationOptionsAttribute>()?.IncludeFields ?? false;
public JsonTypeInfo<Location> Location { get; }
public JsonTypeInfo<NumberTypes> NumberTypes { get; }
public JsonTypeInfo<RealWorldContextTests.MyNestedClass.MyNestedNestedClass> MyNestedNestedClass { get; }
public JsonTypeInfo<object[]> ObjectArray { get; }
public JsonTypeInfo<string> String { get; }
+ public JsonTypeInfo<(string Label1, int Label2, bool)> ValueTupleStringInt32Boolean { get; }
public JsonTypeInfo<RealWorldContextTests.ClassWithEnumAndNullable> ClassWithEnumAndNullable { get; }
public JsonTypeInfo<ClassWithCustomConverter> ClassWithCustomConverter { get; }
public JsonTypeInfo<StructWithCustomConverter> StructWithCustomConverter { get; }
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))]
[JsonSerializable(typeof(object[]))]
[JsonSerializable(typeof(string))]
+ [JsonSerializable(typeof((string Label1, int Label2, bool)))]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))]
[JsonSerializable(typeof(ClassWithCustomConverter))]
[JsonSerializable(typeof(StructWithCustomConverter))]
Assert.Null(MetadataAndSerializationContext.Default.ObjectArray.Serialize);
Assert.Null(MetadataAndSerializationContext.Default.SampleEnum.Serialize);
Assert.Null(MetadataAndSerializationContext.Default.String.Serialize);
+ Assert.NotNull(MetadataAndSerializationContext.Default.ValueTupleStringInt32Boolean.Serialize);
Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithEnumAndNullable.Serialize);
Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithCustomConverter);
Assert.NotNull(MetadataAndSerializationContext.Default.StructWithCustomConverter);
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Metadata)]
+ [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(StructWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)]
Assert.Null(MetadataWithPerTypeAttributeContext.Default.ObjectArray.Serialize);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.SampleEnum.Serialize);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.String.Serialize);
+ Assert.Null(MetadataWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.Serialize);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.Serialize);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverter.Serialize);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverter.Serialize);
}
}
- [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
+ [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata, IncludeFields = true)]
[JsonSerializable(typeof(Location))]
[JsonSerializable(typeof(RepeatedTypes.Location), TypeInfoPropertyName = "RepeatedLocation")]
[JsonSerializable(typeof(NumberTypes))]
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))]
[JsonSerializable(typeof(object[]))]
[JsonSerializable(typeof(string))]
+ [JsonSerializable(typeof((string Label1, int Label2, bool)))]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))]
[JsonSerializable(typeof(ClassWithCustomConverter))]
[JsonSerializable(typeof(StructWithCustomConverter))]
Assert.Null(MetadataContext.Default.ObjectArray.Serialize);
Assert.Null(MetadataContext.Default.SampleEnum.Serialize);
Assert.Null(MetadataContext.Default.String.Serialize);
+ Assert.Null(MetadataContext.Default.ValueTupleStringInt32Boolean.Serialize);
Assert.Null(MetadataContext.Default.ClassWithEnumAndNullable.Serialize);
Assert.Null(MetadataContext.Default.ClassWithCustomConverter.Serialize);
Assert.Null(MetadataContext.Default.StructWithCustomConverter.Serialize);
namespace System.Text.Json.SourceGeneration.Tests
{
+ [JsonSourceGenerationOptions(IncludeFields = true)]
[JsonSerializable(typeof(Location), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(RepeatedTypes.Location), TypeInfoPropertyName = "RepeatedLocation", GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(NumberTypes), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
+ [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(StructWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
Assert.Null(MixedModeContext.Default.ObjectArray.Serialize);
Assert.Null(MixedModeContext.Default.SampleEnum.Serialize);
Assert.Null(MixedModeContext.Default.String.Serialize);
+ Assert.NotNull(MixedModeContext.Default.ValueTupleStringInt32Boolean.Serialize);
Assert.NotNull(MixedModeContext.Default.ClassWithEnumAndNullable.Serialize);
Assert.Null(MixedModeContext.Default.ClassWithCustomConverter.Serialize);
Assert.Null(MixedModeContext.Default.StructWithCustomConverter.Serialize);
}
[Fact]
+ public virtual void RoundTripValueTuple()
+ {
+ bool isIncludeFieldsEnabled = DefaultContext.IsIncludeFieldsEnabled;
+
+ var tuple = (Label1: "string", Label2: 42, true);
+ string expectedJson = isIncludeFieldsEnabled
+ ? "{\"Item1\":\"string\",\"Item2\":42,\"Item3\":true}"
+ : "{}";
+
+ string json = JsonSerializer.Serialize(tuple, DefaultContext.ValueTupleStringInt32Boolean);
+ Assert.Equal(expectedJson, json);
+
+ if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization)
+ {
+ // Deserialization not supported in fast path serialization only mode
+ Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize(json, DefaultContext.ValueTupleStringInt32Boolean));
+ }
+ else
+ {
+ var deserializedTuple = JsonSerializer.Deserialize(json, DefaultContext.ValueTupleStringInt32Boolean);
+ Assert.Equal(isIncludeFieldsEnabled ? tuple : default, deserializedTuple);
+ }
+ }
+
+ [Fact]
public virtual void RoundTripWithCustomConverter_Class()
{
const string Json = "{\"MyInt\":142}";
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))]
[JsonSerializable(typeof(object[]))]
[JsonSerializable(typeof(string))]
+ [JsonSerializable(typeof((string Label1, int Label2, bool)))]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))]
[JsonSerializable(typeof(ClassWithCustomConverter))]
[JsonSerializable(typeof(StructWithCustomConverter))]
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Serialization)]
+ [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(StructWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)]
public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Serialization;
}
- [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
+ [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, IncludeFields = true)]
[JsonSerializable(typeof(Location), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RepeatedTypes.Location), GenerationMode = JsonSourceGenerationMode.Serialization, TypeInfoPropertyName = "RepeatedLocation")]
[JsonSerializable(typeof(NumberTypes), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Serialization)]
+ [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(StructWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)]
Assert.NotNull(SerializationContext.Default.MyNestedNestedClass.Serialize);
Assert.Null(SerializationContext.Default.ObjectArray.Serialize);
Assert.Null(SerializationContext.Default.String.Serialize);
+ Assert.NotNull(SerializationContext.Default.ValueTupleStringInt32Boolean.Serialize);
Assert.NotNull(SerializationContext.Default.ClassWithEnumAndNullable.Serialize);
Assert.Null(SerializationContext.Default.ClassWithCustomConverter.Serialize);
Assert.Null(SerializationContext.Default.StructWithCustomConverter.Serialize);
Assert.Null(SerializationWithPerTypeAttributeContext.Default.ObjectArray.Serialize);
Assert.Null(SerializationWithPerTypeAttributeContext.Default.SampleEnum.Serialize);
Assert.Null(SerializationWithPerTypeAttributeContext.Default.String.Serialize);
+ Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.Serialize);
Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.Serialize);
Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverter.Serialize);
Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverter.Serialize);