Skip to content

Commit 2f7deae

Browse files
authored
Merge pull request #401 from ArangoDB-Community/feature-3.8/DE-283-PostCreateViewAsync-LinkProperties-not-serializing-correctly
Fixed dictionary item value serialization issue
2 parents 154a398 + a049c0b commit 2f7deae

File tree

6 files changed

+114
-15
lines changed

6 files changed

+114
-15
lines changed

arangodb-net-standard.Test/Serialization/JsonNetApiClientSerializationTest.cs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ public void Serialize_ShouldNotCamelCaseBindVars_WhenSerializingPostCursorBody()
159159
};
160160
var serialization = new JsonNetApiClientSerialization();
161161

162-
byte[] jsonBytes = serialization.Serialize(body, new ApiClientSerializationOptions(true, true));
162+
byte[] jsonBytes = serialization.Serialize(body, new ApiClientSerializationOptions(
163+
useCamelCasePropertyNames: true,
164+
ignoreNullValues: true,
165+
camelCasePropertyNamesOfObjectValuesInDictionaries: false));
163166

164167
string jsonString = Encoding.UTF8.GetString(jsonBytes);
165168

@@ -169,6 +172,31 @@ public void Serialize_ShouldNotCamelCaseBindVars_WhenSerializingPostCursorBody()
169172
Assert.DoesNotContain("dontCamelCaseKey", jsonString);
170173
}
171174

175+
[Fact]
176+
public void Serialize_ShouldCamelCaseBindVars_WhenSerializingPostCursorBody()
177+
{
178+
var body = new PostCursorBody
179+
{
180+
BindVars = new Dictionary<string, object>
181+
{
182+
["DontCamelCaseKey"] = new { DontCamelCaseMe = true }
183+
}
184+
};
185+
var serialization = new JsonNetApiClientSerialization();
186+
187+
byte[] jsonBytes = serialization.Serialize(body, new ApiClientSerializationOptions(
188+
useCamelCasePropertyNames: true,
189+
ignoreNullValues: true,
190+
camelCasePropertyNamesOfObjectValuesInDictionaries: true));
191+
192+
string jsonString = Encoding.UTF8.GetString(jsonBytes);
193+
194+
Assert.Contains("DontCamelCaseKey", jsonString);
195+
Assert.DoesNotContain("dontCamelCaseKey", jsonString);
196+
Assert.Contains("dontCamelCaseMe", jsonString);
197+
Assert.DoesNotContain("DontCamelCaseMe", jsonString);
198+
}
199+
172200
[Fact]
173201
public void Serialize_ShouldNotCamelCaseParams_WhenSerializingPostTransactionBody()
174202
{
@@ -182,7 +210,10 @@ public void Serialize_ShouldNotCamelCaseParams_WhenSerializingPostTransactionBod
182210

183211
var serialization = new JsonNetApiClientSerialization();
184212

185-
byte[] jsonBytes = serialization.Serialize(body, new ApiClientSerializationOptions(true, true));
213+
byte[] jsonBytes = serialization.Serialize(body, new ApiClientSerializationOptions(
214+
useCamelCasePropertyNames: true,
215+
ignoreNullValues: true,
216+
camelCasePropertyNamesOfObjectValuesInDictionaries: false));
186217

187218
string jsonString = Encoding.UTF8.GetString(jsonBytes);
188219

@@ -192,6 +223,33 @@ public void Serialize_ShouldNotCamelCaseParams_WhenSerializingPostTransactionBod
192223
Assert.DoesNotContain("dontCamelCaseKey", jsonString);
193224
}
194225

226+
227+
[Fact]
228+
public void Serialize_ShouldCamelCaseParams_WhenSerializingPostTransactionBody()
229+
{
230+
var body = new PostTransactionBody
231+
{
232+
Params = new Dictionary<string, object>
233+
{
234+
["DontCamelCaseKey"] = new { DontCamelCaseMe = true }
235+
}
236+
};
237+
238+
var serialization = new JsonNetApiClientSerialization();
239+
240+
byte[] jsonBytes = serialization.Serialize(body, new ApiClientSerializationOptions(
241+
useCamelCasePropertyNames: true,
242+
ignoreNullValues: true,
243+
camelCasePropertyNamesOfObjectValuesInDictionaries: true));
244+
245+
string jsonString = Encoding.UTF8.GetString(jsonBytes);
246+
247+
Assert.Contains("DontCamelCaseKey", jsonString);
248+
Assert.DoesNotContain("dontCamelCaseKey", jsonString);
249+
Assert.Contains("dontCamelCaseMe", jsonString);
250+
Assert.DoesNotContain("DontCamelCaseMe", jsonString);
251+
}
252+
195253
[Fact]
196254
public void Serialize_ShouldNotIgnoreNull_WhenSerializingPostCursorBody()
197255
{

arangodb-net-standard/Serialization/ApiClientSerialization.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ public abstract class ApiClientSerialization : IApiClientSerialization
1616
useCamelCasePropertyNames: false,
1717
ignoreNullValues: true,
1818
useStringEnumConversion: false,
19-
ignoreMissingMember: true);
19+
ignoreMissingMember: true,
20+
camelCasePropertyNamesOfObjectValuesInDictionaries: false);
2021

2122
/// <summary>
2223
/// Deserializes the data structure contained by the specified stream

arangodb-net-standard/Serialization/ApiClientSerializationOptions.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,34 @@ public class ApiClientSerializationOptions
2727
/// </summary>
2828
public bool UseStringEnumConversion { get; set; }
2929

30+
/// <summary>
31+
/// True to camel case the names of properties of object values
32+
/// in dictionaries (i.e. CamelCaseMe => "camelCaseMe").
33+
/// False to leave the names of properties of object values
34+
/// in dictionaries as they are (i.e. DontCamelCaseMe => "DontCamelCaseMe")
35+
/// </summary>
36+
public bool CamelCasePropertyNamesOfObjectValuesInDictionaries { get; set; }
37+
3038
/// <summary>
3139
/// Create serialization options.
3240
/// </summary>
3341
/// <param name="useCamelCasePropertyNames">Whether property names should be serialized using camelCase.</param>
3442
/// <param name="ignoreNullValues">Whether null values should be ignored - i.e. not defined at all in the serialized string.</param>
3543
/// <param name="useStringEnumConversion">Whether to serialize enum values to a string value instead of an integer.</param>
3644
/// <param name="ignoreMissingMember">Whether missing members should be ignored.</param>
45+
/// <param name="camelCasePropertyNamesOfObjectValuesInDictionaries">Whether to camel case the names of properties of object values in dictionaries.</param>
3746
public ApiClientSerializationOptions(
3847
bool useCamelCasePropertyNames,
3948
bool ignoreNullValues,
4049
bool useStringEnumConversion = false,
41-
bool ignoreMissingMember = true)
50+
bool ignoreMissingMember = true,
51+
bool camelCasePropertyNamesOfObjectValuesInDictionaries = false)
4252
{
4353
UseCamelCasePropertyNames = useCamelCasePropertyNames;
4454
IgnoreNullValues = ignoreNullValues;
4555
UseStringEnumConversion = useStringEnumConversion;
4656
IgnoreMissingMember = ignoreMissingMember;
57+
CamelCasePropertyNamesOfObjectValuesInDictionaries = camelCasePropertyNamesOfObjectValuesInDictionaries;
4758
}
4859
}
49-
}
60+
}

arangodb-net-standard/Serialization/CamelCasePropertyNamesExceptDictionaryContractResolver.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ namespace ArangoDBNetStandard.Serialization
1010
/// </summary>
1111
public class CamelCasePropertyNamesExceptDictionaryContractResolver : DefaultContractResolver
1212
{
13-
public CamelCasePropertyNamesExceptDictionaryContractResolver()
13+
private ApiClientSerializationOptions _serializationOptions;
14+
public CamelCasePropertyNamesExceptDictionaryContractResolver(ApiClientSerializationOptions serializationOptions)
1415
{
1516
NamingStrategy = new CamelCaseNamingStrategy();
17+
_serializationOptions = serializationOptions;
1618
}
1719

1820
protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
1921
{
2022
JsonDictionaryContract contract = base.CreateDictionaryContract(objectType);
2123
contract.DictionaryKeyResolver = propertyName => propertyName;
22-
contract.ItemConverter = new DictionaryValueConverter();
24+
contract.ItemConverter = new DictionaryValueConverter(_serializationOptions);
2325
return contract;
2426
}
2527
}

arangodb-net-standard/Serialization/DictionaryValueConverter.cs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Newtonsoft.Json;
22
using System;
3+
using Newtonsoft.Json.Converters;
34

45
namespace ArangoDBNetStandard.Serialization
56
{
@@ -9,10 +10,12 @@ namespace ArangoDBNetStandard.Serialization
910
/// </summary>
1011
public class DictionaryValueConverter : JsonConverter
1112
{
12-
private static JsonSerializer _serializer = new JsonSerializer
13+
private ApiClientSerializationOptions _serializationOptions;
14+
15+
public DictionaryValueConverter(ApiClientSerializationOptions serializationOptions)
1316
{
14-
NullValueHandling = NullValueHandling.Include
15-
};
17+
_serializationOptions = serializationOptions;
18+
}
1619

1720
public override bool CanConvert(Type objectType)
1821
{
@@ -26,9 +29,33 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
2629

2730
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
2831
{
29-
// Use our local serializer for writing instead of the passed-in serializer
30-
_serializer.Serialize(writer, value);
32+
// Use a local serializer for writing instead of the passed-in serializer
33+
JsonSerializer mySerializer;
34+
if (_serializationOptions != null && _serializationOptions.CamelCasePropertyNamesOfObjectValuesInDictionaries)
35+
{
36+
mySerializer = new JsonSerializer
37+
{
38+
MissingMemberHandling = _serializationOptions.IgnoreMissingMember ? MissingMemberHandling.Ignore : MissingMemberHandling.Error,
39+
NullValueHandling = _serializationOptions.IgnoreNullValues ? NullValueHandling.Ignore : NullValueHandling.Include
40+
};
41+
if (_serializationOptions.UseStringEnumConversion)
42+
{
43+
var stringEnumConverter = new StringEnumConverter();
44+
mySerializer.Converters.Add(stringEnumConverter);
45+
}
46+
if (_serializationOptions.UseCamelCasePropertyNames)
47+
{
48+
mySerializer.ContractResolver = new CamelCasePropertyNamesExceptDictionaryContractResolver(_serializationOptions);
49+
}
50+
}
51+
else
52+
{
53+
mySerializer = new JsonSerializer
54+
{
55+
NullValueHandling = NullValueHandling.Include
56+
};
57+
}
58+
mySerializer.Serialize(writer, value);
3159
}
3260
}
33-
34-
}
61+
}

arangodb-net-standard/Serialization/JsonNetApiClientSerialization.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public override string SerializeToString<T>(T item, ApiClientSerializationOption
8383

8484
if (serializationOptions.UseCamelCasePropertyNames)
8585
{
86-
jsonSettings.ContractResolver = new CamelCasePropertyNamesExceptDictionaryContractResolver();
86+
jsonSettings.ContractResolver = new CamelCasePropertyNamesExceptDictionaryContractResolver(serializationOptions);
8787
}
8888

8989
string json = JsonConvert.SerializeObject(item, jsonSettings);

0 commit comments

Comments
 (0)