Skip to content

Commit a61c4cd

Browse files
committed
allow for custom serialization
1 parent 345c791 commit a61c4cd

File tree

12 files changed

+255
-32
lines changed

12 files changed

+255
-32
lines changed

src/.editorconfig

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Rules in this file were initially inferred by Visual Studio IntelliCode from the C:\code\TableStorage.Abstractions.POCO\src codebase based on best match to current usage at 10/1/2021
2+
# You can modify the rules from these initially generated values to suit your own policies
3+
# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
4+
[*.cs]
5+
6+
7+
#Core editorconfig formatting - indentation
8+
9+
#use hard tabs for indentation
10+
indent_style = tab
11+
12+
#Formatting - new line options
13+
14+
#place else statements on a new line
15+
csharp_new_line_before_else = true
16+
#require braces to be on a new line for methods and types (also known as "Allman" style)
17+
csharp_new_line_before_open_brace = methods, types
18+
19+
#Formatting - organize using options
20+
21+
#sort System.* using directives alphabetically, and place them before other usings
22+
dotnet_sort_system_directives_first = true
23+
24+
#Formatting - spacing options
25+
26+
#require a space before the colon for bases or interfaces in a type declaration
27+
csharp_space_after_colon_in_inheritance_clause = true
28+
#require a space after a keyword in a control flow statement such as a for loop
29+
csharp_space_after_keywords_in_control_flow_statements = true
30+
#require a space before the colon for bases or interfaces in a type declaration
31+
csharp_space_before_colon_in_inheritance_clause = true
32+
#remove space between method call name and opening parenthesis
33+
csharp_space_between_method_call_name_and_opening_parenthesis = false
34+
#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call
35+
csharp_space_between_method_call_parameter_list_parentheses = false
36+
#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list.
37+
csharp_space_between_method_declaration_parameter_list_parentheses = false
38+
39+
#Formatting - wrapping options
40+
41+
#leave code block on single line
42+
csharp_preserve_single_line_blocks = true
43+
44+
#Style - Code block preferences
45+
46+
#prefer curly braces even for one line of code
47+
csharp_prefer_braces = true:suggestion
48+
49+
#Style - expression bodied member options
50+
51+
#prefer block bodies for methods
52+
csharp_style_expression_bodied_methods = false:suggestion
53+
54+
#Style - implicit and explicit types
55+
56+
#prefer explicit type over var in all cases, unless overridden by another code style rule
57+
csharp_style_var_elsewhere = false:suggestion
58+
59+
#Style - language keyword and framework type options
60+
61+
#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
62+
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
63+
64+
#Style - Miscellaneous preferences
65+
66+
#prefer anonymous functions over local functions
67+
csharp_style_pattern_local_over_anonymous_function = false:suggestion
68+
69+
#Style - modifier options
70+
71+
#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
72+
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
73+
74+
#Style - Modifier preferences
75+
76+
#when this rule is set to a list of modifiers, prefer the specified ordering.
77+
csharp_preferred_modifier_order = public,private,readonly,static:suggestion
78+
79+
#Style - qualification options
80+
81+
#prefer fields not to be prefaced with this. or Me. in Visual Basic
82+
dotnet_style_qualification_for_field = false:suggestion
83+
#prefer properties not to be prefaced with this. or Me. in Visual Basic
84+
dotnet_style_qualification_for_property = false:suggestion

src/TableStorage.Abstractions.POCO.SecondaryIndexes/TableStorage.Abstractions.POCO.SecondaryIndexes.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
</ItemGroup>
2626

2727
<ItemGroup>
28-
<PackageReference Include="TableStorage.Abstractions.POCO" Version="2.7.0" />
28+
<PackageReference Include="TableStorage.Abstractions.POCO" Version="2.7.1" />
2929
</ItemGroup>
3030

3131
</Project>

src/TableStorage.Abstractions.POCO.sln

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TableStorage.Abstractions.P
1111
EndProject
1212
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TableStorage.Abstractions.POCO.Tests", "..\tests\TableStorage.Abstractions.POCO.Tests\TableStorage.Abstractions.POCO.Tests.csproj", "{005D8280-599C-4952-BBAB-EDAF51BFF70F}"
1313
EndProject
14+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{511776B6-B4CF-4243-BED5-AE1CB30E461B}"
15+
ProjectSection(SolutionItems) = preProject
16+
.editorconfig = .editorconfig
17+
EndProjectSection
18+
EndProject
1419
Global
1520
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1621
Debug|Any CPU = Debug|Any CPU

src/TableStorage.Abstractions.POCO/CalculatedKeysConverter.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Linq.Expressions;
33
using Microsoft.Azure.Cosmos.Table;
4+
using Newtonsoft.Json;
45
using TableStorage.Abstractions.TableEntityConverters;
56

67
namespace TableStorage.Abstractions.POCO
@@ -10,24 +11,30 @@ public class CalculatedKeysConverter<T, TPartitionKey, TRowKey> : IKeysConverter
1011
{
1112
private readonly KeyMapper<T, TPartitionKey> _partitionMapper;
1213
private readonly KeyMapper<T, TRowKey> _rowMapper;
14+
private readonly JsonSerializerSettings _jsonSerializerSettings;
1315
private readonly Expression<Func<T, object>>[] _ignoredProperties;
1416

15-
public CalculatedKeysConverter(KeyMapper<T, TPartitionKey> partitionMapper, KeyMapper<T,TRowKey> rowMapper,
17+
public CalculatedKeysConverter(KeyMapper<T, TPartitionKey> partitionMapper, KeyMapper<T,TRowKey> rowMapper, JsonSerializerSettings jsonSerializerSettings,
1618
params Expression<Func<T, object>>[] ignoredProperties)
1719
{
1820
_partitionMapper = partitionMapper;
1921
_rowMapper = rowMapper;
22+
_jsonSerializerSettings = jsonSerializerSettings;
2023
_ignoredProperties = ignoredProperties;
2124
}
25+
public CalculatedKeysConverter(KeyMapper<T, TPartitionKey> partitionMapper, KeyMapper<T, TRowKey> rowMapper,
26+
params Expression<Func<T, object>>[] ignoredProperties) : this(partitionMapper, rowMapper, new JsonSerializerSettings(), ignoredProperties)
27+
{
28+
}
2229
public DynamicTableEntity ToEntity(T obj)
2330
{
24-
return obj.ToTableEntity(_partitionMapper.ToKey(obj), _rowMapper.ToKey(obj), _ignoredProperties);
31+
return obj.ToTableEntity(_partitionMapper.ToKey(obj), _rowMapper.ToKey(obj), _jsonSerializerSettings, _ignoredProperties);
2532
}
2633

2734
public T FromEntity(DynamicTableEntity entity)
2835
{
2936
return entity.FromTableEntity(_partitionMapper.KeyProperty, _partitionMapper.FromKey, _rowMapper.KeyProperty,
30-
_rowMapper.FromKey);
37+
_rowMapper.FromKey, _jsonSerializerSettings);
3138
}
3239

3340
public string PartitionKey(TPartitionKey key)

src/TableStorage.Abstractions.POCO/PocoTableStore.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Reflection;
99
using System.Threading.Tasks;
1010
using Microsoft.Azure.Cosmos.Table;
11+
using Newtonsoft.Json;
1112
using TableStorage.Abstractions.Models;
1213
using TableStorage.Abstractions.Store;
1314
using Useful.Extensions;
@@ -29,7 +30,7 @@ namespace TableStorage.Abstractions.POCO
2930
/// <param name="storageConnectionString">The azure storage connection string.</param>
3031
/// <param name="partitionProperty">The property to be used as a partition key.</param>
3132
/// <param name="rowProperty">The property to be used as a row key.</param>
32-
/// <param name="tableStorageOptions">The table storage options.</param>
33+
/// <param name="options">The table storage options.</param>
3334
/// <param name="ignoredProperties">The properties that should not be serialized.</param>
3435
/// <exception cref="ArgumentNullException">tableName
3536
/// or
@@ -39,22 +40,19 @@ namespace TableStorage.Abstractions.POCO
3940
/// or
4041
/// rowProperty</exception>
4142
public PocoTableStore(string tableName, string storageConnectionString, Expression<Func<T, object>> partitionProperty,
42-
Expression<Func<T, object>> rowProperty, TableStorageOptions tableStorageOptions = null, params Expression<Func<T, object>>[] ignoredProperties)
43+
Expression<Func<T, object>> rowProperty, PocoTableStoreOptions options = null, params Expression<Func<T, object>>[] ignoredProperties)
4344
{
4445
if (tableName == null) throw new ArgumentNullException(nameof(tableName));
4546
if (storageConnectionString == null) throw new ArgumentNullException(nameof(storageConnectionString));
4647
if (partitionProperty == null) throw new ArgumentNullException(nameof(partitionProperty));
4748
if (rowProperty == null) throw new ArgumentNullException(nameof(rowProperty));
4849

49-
50-
_keysConverter = new SimpleKeysConverter<T, TPartitionKey, TRowKey>(partitionProperty, rowProperty, ignoredProperties);
50+
options ??= new PocoTableStoreOptions();
51+
_keysConverter = new SimpleKeysConverter<T, TPartitionKey, TRowKey>(partitionProperty, rowProperty, options.JsonSerializerSettings, ignoredProperties);
5152
_tableName = tableName;
52-
tableStorageOptions = tableStorageOptions ?? new TableStorageOptions();
53-
_tableStore = new TableStore<DynamicTableEntity>(tableName, storageConnectionString, tableStorageOptions);
54-
55-
}
56-
53+
_tableStore = new TableStore<DynamicTableEntity>(tableName, storageConnectionString, options.TableStorageOptions);
5754

55+
}
5856

5957
/// <summary>
6058
/// Initializes a new instance of the <see cref="PocoTableStore{T, TPartitionKey, TRowKey}" /> class.
@@ -78,7 +76,7 @@ public PocoTableStore(string tableName, string storageConnectionString,
7876

7977
_keysConverter = keysConverter;
8078
_tableName = tableName;
81-
tableStorageOptions = tableStorageOptions ?? new TableStorageOptions();
79+
tableStorageOptions ??= new TableStorageOptions();
8280
_tableStore = new TableStore<DynamicTableEntity>(tableName, storageConnectionString, tableStorageOptions);
8381

8482
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Newtonsoft.Json;
5+
using TableStorage.Abstractions.Store;
6+
7+
namespace TableStorage.Abstractions.POCO
8+
{
9+
public class PocoTableStoreOptions
10+
{
11+
public PocoTableStoreOptions(TableStorageOptions tableStorageOptions, JsonSerializerSettings jsonSerializerSettings)
12+
{
13+
TableStorageOptions = tableStorageOptions;
14+
JsonSerializerSettings = jsonSerializerSettings;
15+
}
16+
public PocoTableStoreOptions(TableStorageOptions tableStorageOptions) : this(tableStorageOptions, new JsonSerializerSettings())
17+
{
18+
}
19+
public PocoTableStoreOptions(JsonSerializerSettings jsonSerializerSettings) : this(new TableStorageOptions(), jsonSerializerSettings)
20+
{
21+
}
22+
23+
public PocoTableStoreOptions() : this(new TableStorageOptions(), new JsonSerializerSettings())
24+
{
25+
}
26+
27+
public TableStorageOptions TableStorageOptions { get; }
28+
public JsonSerializerSettings JsonSerializerSettings { get; }
29+
}
30+
}

src/TableStorage.Abstractions.POCO/SimpleKeysConverter.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Linq.Expressions;
33
using Microsoft.Azure.Cosmos.Table;
4+
using Newtonsoft.Json;
45
using TableStorage.Abstractions.TableEntityConverters;
56

67
namespace TableStorage.Abstractions.POCO
@@ -9,25 +10,27 @@ public class SimpleKeysConverter<T, TPartitionKey, TRowKey> : IKeysConverter<T,
910
where T : new()
1011
{
1112
private readonly Expression<Func<T, object>>[] _ignoredProperties;
13+
private readonly JsonSerializerSettings _jsonSerializerSettings;
1214
private readonly Expression<Func<T, object>> _partitionProperty;
1315
private readonly Expression<Func<T, object>> _rowProperty;
1416

1517
public SimpleKeysConverter(Expression<Func<T, object>> partitionProperty,
16-
Expression<Func<T, object>> rowProperty, Expression<Func<T, object>>[] ignoredProperties)
18+
Expression<Func<T, object>> rowProperty, JsonSerializerSettings jsonSerializerSettings, Expression<Func<T, object>>[] ignoredProperties)
1719
{
1820
_partitionProperty = partitionProperty;
1921
_rowProperty = rowProperty;
2022
_ignoredProperties = ignoredProperties;
23+
_jsonSerializerSettings = jsonSerializerSettings;
2124
}
2225

2326
public DynamicTableEntity ToEntity(T obj)
2427
{
25-
return obj.ToTableEntity(_partitionProperty, _rowProperty, _ignoredProperties);
28+
return obj.ToTableEntity(_partitionProperty, _rowProperty, _jsonSerializerSettings, _ignoredProperties);
2629
}
2730

2831
public T FromEntity(DynamicTableEntity entity)
2932
{
30-
return entity.FromTableEntity<T, TPartitionKey, TRowKey>(_partitionProperty, _rowProperty);
33+
return entity.FromTableEntity<T, TPartitionKey, TRowKey>(_partitionProperty, _rowProperty, _jsonSerializerSettings);
3134
}
3235

3336
public string PartitionKey(TPartitionKey key)

src/TableStorage.Abstractions.POCO/TableStorage.Abstractions.POCO.csproj

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
5-
<Version>2.7.1.0</Version>
5+
<Version>3.0.0.0</Version>
66
<Authors>Giovanni Galbo</Authors>
77
<Company>Giovanni Galbo</Company>
88
<Description>
@@ -16,32 +16,33 @@
1616

1717
The library will convert simple properties to fields in Azure Table Storage. Complex types will serialize as json.
1818
</Description>
19-
<Copyright>© Giovanni Galbo 2020</Copyright>
19+
<Copyright>© Giovanni Galbo 2021</Copyright>
2020
<PackageLicenseUrl></PackageLicenseUrl>
2121
<PackageProjectUrl>https://github.com/giometrix/TableStorage.Abstractions.POCO</PackageProjectUrl>
2222
<RepositoryUrl>https://github.com/giometrix/TableStorage.Abstractions.POCO</RepositoryUrl>
2323
<PackageTags>table-storage azure-table-storage poco table-entities tableentity</PackageTags>
24-
<PackageReleaseNotes>Added sourcelink</PackageReleaseNotes>
24+
<PackageReleaseNotes>Allows for custom json serialization options</PackageReleaseNotes>
2525
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
2626
<PackageLicenseExpression>MIT</PackageLicenseExpression>
2727
<PublishRepositoryUrl>true</PublishRepositoryUrl>
2828
<EmbedUntrackedSources>true</EmbedUntrackedSources>
2929
<IncludeSymbols>true</IncludeSymbols>
3030
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
3131

32-
<AssemblyVersion>2.7.1.0</AssemblyVersion>
33-
<FileVersion>2.7.1.0</FileVersion>
32+
<AssemblyVersion>3.0.0.0</AssemblyVersion>
33+
<FileVersion>3.0.0.0</FileVersion>
3434
<PackageIcon>xtensible-x.png</PackageIcon>
3535
<PackageIconUrl />
36+
<LangVersion>latest</LangVersion>
3637
</PropertyGroup>
3738

3839
<ItemGroup>
3940
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
4041
<PrivateAssets>all</PrivateAssets>
4142
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
4243
</PackageReference>
43-
<PackageReference Include="TableStorage.Abstractions" Version="3.2.2" />
44-
<PackageReference Include="TableStorage.Abstractions.TableEntityConverters" Version="1.3.1" />
44+
<PackageReference Include="TableStorage.Abstractions" Version="3.2.4" />
45+
<PackageReference Include="TableStorage.Abstractions.TableEntityConverters" Version="1.4.0" />
4546
<PackageReference Include="Xtensible.Time.Clock" Version="1.1.0" />
4647
</ItemGroup>
4748

tests/TableStorage.Abstractions.POCO.SecondaryIndexes.Tests/TableStorage.Abstractions.POCO.SecondaryIndexes.Tests.csproj

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
11-
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
12-
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
13-
<PackageReference Include="coverlet.collector" Version="1.2.0" />
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
11+
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
12+
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" />
13+
<PackageReference Include="coverlet.collector" Version="3.1.0">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
1417
</ItemGroup>
1518

1619
<ItemGroup>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Linq;
6+
7+
namespace TableStorage.Abstractions.POCO.Tests
8+
{
9+
public class KeysJsonConverter : JsonConverter
10+
{
11+
private readonly Type[] _types;
12+
13+
public override bool CanRead => false;
14+
15+
public KeysJsonConverter(params Type[] types)
16+
{
17+
_types = types;
18+
}
19+
20+
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
21+
{
22+
var t = JToken.FromObject(value);
23+
24+
if (t.Type != JTokenType.Object)
25+
{
26+
t.WriteTo(writer);
27+
}
28+
else
29+
{
30+
var o = (JObject)t;
31+
IList<string> propertyNames = o.Properties().Select(p => p.Name).ToList();
32+
33+
o.AddFirst(new JProperty("Keys", new JArray(propertyNames)));
34+
35+
o.WriteTo(writer);
36+
}
37+
}
38+
39+
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
40+
JsonSerializer serializer)
41+
{
42+
throw new NotImplementedException(
43+
"Unnecessary because CanRead is false. The type will skip the converter.");
44+
}
45+
46+
public override bool CanConvert(Type objectType)
47+
{
48+
return _types.Any(t => t == objectType);
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)