Skip to content

Commit 880f5b9

Browse files
committed
Merge branch 'hotfix/v1.4.1'
2 parents b66cd8e + 3edc7a8 commit 880f5b9

18 files changed

Lines changed: 143 additions & 90 deletions

JsonTestClasses.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ public class FooAttributes
209209
[DataMember(Name = "YesNo")]
210210
public bool BoolProperty { get; set; }
211211
}
212-
213212
}
214213

215214
// These are here so the attribute test works. This is a standalone file without references, so Roslyn won't know the attributes otherwise.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Linq;
2+
3+
namespace CodeCaster.SerializeThis.Serialization.Json
4+
{
5+
public static class AttributeExtensions
6+
{
7+
/// <summary>
8+
/// Returns the Nth constructor argument (if passed non-null argument), or the given property name's value, or null if not found.
9+
///
10+
/// For example `[Foo("Bar")]` will return "Bar" for GetArgOrNamedProperty(0, null), `[Foo(Baz = "Bar"]` will return "Bar" for GetArgOrNamedProperty(null, "Baz").
11+
/// </summary>
12+
public static string GetArgOrNamedProperty(this AttributeInfo attribute, int? constructorArgumentIndex, string propertyName)
13+
{
14+
15+
if (constructorArgumentIndex.HasValue && attribute.ConstructorArguments.Length == constructorArgumentIndex + 1)
16+
{
17+
return attribute.ConstructorArguments[0]?.ToString();
18+
}
19+
20+
if (string.IsNullOrWhiteSpace(propertyName))
21+
{
22+
return null;
23+
}
24+
25+
return attribute.Properties.Where(namedArg => namedArg.Key == propertyName)
26+
.Select(namedArg => namedArg.Value?.ToString())
27+
.FirstOrDefault();
28+
}
29+
}
30+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Linq;
2+
3+
namespace CodeCaster.SerializeThis.Serialization.Json
4+
{
5+
public static class ClassInfoExtensions
6+
{
7+
/// <summary>
8+
/// Returns the declared property name, or its name if overridden through any known attributes such as [JsonProperty], [DataMember].
9+
/// </summary>
10+
public static string GetPropertyName(this ClassInfo typeInfo, ClassInfo containingTypeInfo)
11+
{
12+
return typeInfo.GetPropertyNameFromAttributes(containingTypeInfo)
13+
?? typeInfo.Name;
14+
}
15+
16+
private static string GetPropertyNameFromAttributes(this ClassInfo typeInfo, ClassInfo containingTypeInfo)
17+
{
18+
if (!typeInfo.Attributes.Any())
19+
{
20+
return null;
21+
}
22+
23+
foreach (var attribute in typeInfo.Attributes)
24+
{
25+
switch (attribute.Name)
26+
{
27+
case TypeNameConstants.NewtonsoftJsonPropertyAttribute:
28+
return attribute.GetArgOrNamedProperty(0, TypeNameConstants.PropertyName);
29+
30+
case TypeNameConstants.SystemTextJsonPropertyAttribute:
31+
return attribute.GetArgOrNamedProperty(0, TypeNameConstants.Name);
32+
33+
// [DataMember] only applies inside a class marked with [DataContract].
34+
case TypeNameConstants.DataMemberAttribute:
35+
return containingTypeInfo?.Class.Attributes.Any(a => a.Name == TypeNameConstants.DataContractAttribute) == true
36+
? attribute.GetArgOrNamedProperty(null, TypeNameConstants.Name)
37+
: null;
38+
39+
default:
40+
continue;
41+
}
42+
}
43+
44+
return null;
45+
}
46+
}
47+
}

src/CodeCaster.SerializeThis.Serialization.Json/CodeCaster.SerializeThis.Serialization.Json.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@
4444
<Compile Include="..\SolutionInfo.cs">
4545
<Link>Properties\SolutionInfo.cs</Link>
4646
</Compile>
47+
<Compile Include="ClassInfoExtensions.cs" />
4748
<Compile Include="JsonSerializer.cs" />
4849
<Compile Include="Properties\AssemblyInfo.cs" />
50+
<Compile Include="AttributeExtensions.cs" />
51+
<Compile Include="TypeNameConstants.cs" />
4952
</ItemGroup>
5053
<ItemGroup>
5154
<ProjectReference Include="..\CodeCaster.SerializeThis.Serialization\CodeCaster.SerializeThis.Serialization.csproj">

src/CodeCaster.SerializeThis.Serialization.Json/JsonSerializer.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ private JObject GetComplexType(ClassInfo toSerialize)
4646

4747
foreach (var child in toSerialize.Class.Children)
4848
{
49+
var propertyName = child.GetPropertyName(toSerialize);
4950
var childProperty = SerializeChild(child);
50-
existing[child.Name] = childProperty;
51+
existing[propertyName] = childProperty;
5152
}
5253

5354
return existing;
5455
}
55-
56+
5657
private JToken SerializeChild(ClassInfo child)
5758
{
5859
if (child.Class.CollectionType == CollectionType.Dictionary)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace CodeCaster.SerializeThis.Serialization.Json
2+
{
3+
public static class TypeNameConstants
4+
{
5+
public const string NewtonsoftJsonPropertyAttribute = "Newtonsoft.Json.JsonPropertyAttribute";
6+
7+
public const string SystemTextJsonPropertyAttribute = "System.Text.Json.JsonPropertyNameAttribute";
8+
9+
public const string DataMemberAttribute = "System.Runtime.Serialization.DataMemberAttribute";
10+
11+
public const string DataContractAttribute = "System.Runtime.Serialization.DataContractAttribute";
12+
13+
14+
public const string Name = "Name";
15+
16+
public const string PropertyName = "PropertyName";
17+
}
18+
}
Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
1-
using Microsoft.CodeAnalysis;
1+
using System;
2+
using System.Collections.Immutable;
3+
using Microsoft.CodeAnalysis;
24
using System.Linq;
35

46
namespace CodeCaster.SerializeThis.Serialization.Roslyn
57
{
68
public static class AttributeDataExtensions
79
{
8-
/// <summary>
9-
/// Returns the Nth constructor argument (if passed non-null argument), or the given property name's value.
10-
///
11-
/// For example `[Foo("Bar")]` will return "Bar" for GetArgOrNamedProperty(0, null), `[Foo(Baz = "Bar"]` will return "Bar" for GetArgOrNamedProperty(null, "Baz").
12-
/// </summary>
13-
public static string GetArgOrNamedProperty(this AttributeData attribute, int? constructorArgumentIndex, string propertyName)
10+
public static AttributeInfo[] Map(this ImmutableArray<AttributeData> attributes)
1411
{
15-
if (constructorArgumentIndex.HasValue && attribute.ConstructorArguments.Length == constructorArgumentIndex + 1)
16-
{
17-
return attribute.ConstructorArguments[0].Value?.ToString();
18-
}
19-
20-
if (string.IsNullOrWhiteSpace(propertyName))
21-
{
22-
return null;
23-
}
24-
25-
return attribute.NamedArguments.Where(namedArg => namedArg.Key == propertyName)
26-
.Select(namedArg => namedArg.Value.Value?.ToString())
27-
.FirstOrDefault();
12+
return attributes == null
13+
? Array.Empty<AttributeInfo>()
14+
: attributes.Select(a => new AttributeInfo
15+
{
16+
Name = a.AttributeClass.GetTypeName(withGenericParameterNames: true),
17+
ConstructorArguments = a.ConstructorArguments.Select(ca => ca.Value).ToArray(),
18+
Properties = a.NamedArguments.ToDictionary(na => na.Key, na => na.Value.Value),
19+
})
20+
.ToArray();
2821
}
2922
}
3023
}

src/CodeCaster.SerializeThis.Serialization.Roslyn/CodeCaster.SerializeThis.Serialization.Roslyn.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
</Compile>
5151
<Compile Include="AttributeDataExtensions.cs" />
5252
<Compile Include="Properties\AssemblyInfo.cs" />
53-
<Compile Include="PropertySymbolExtensions.cs" />
5453
<Compile Include="TypeNameConstants.cs" />
5554
<Compile Include="TypeSymbolExtensions.cs" />
5655
<Compile Include="TypeSymbolParser.cs" />

src/CodeCaster.SerializeThis.Serialization.Roslyn/PropertySymbolExtensions.cs

Lines changed: 0 additions & 42 deletions
This file was deleted.

src/CodeCaster.SerializeThis.Serialization.Roslyn/TypeNameConstants.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,5 @@ public static class TypeNameConstants
77
public const string GenericCollectionInterface = "System.Collections.Generic.ICollection";
88

99
public const string GenericDictionaryInterface = "System.Collections.Generic.IDictionary";
10-
11-
public const string NewtonsoftJsonPropertyAttribute = "Newtonsoft.Json.JsonPropertyAttribute";
12-
13-
public const string SystemTextJsonPropertyAttribute = "System.Text.Json.JsonPropertyNameAttribute";
14-
15-
public const string DataMemberAttribute = "System.Runtime.Serialization.DataMemberAttribute";
16-
17-
public const string DataContractAttribute = "System.Runtime.Serialization.DataContractAttribute";
18-
19-
20-
public const string Name = "Name";
21-
22-
public const string PropertyName = "PropertyName";
23-
2410
}
2511
}

0 commit comments

Comments
 (0)