Skip to content

Commit 148396a

Browse files
authored
Merge pull request #307 from greg-ww/main
Add support to JsonSerializationWriter.WriteNonParsableObjectValue for anonymous objects.
2 parents 1eca71b + 799c405 commit 148396a

File tree

4 files changed

+66
-6
lines changed

4 files changed

+66
-6
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.9.12] - 2024-07-30
11+
12+
- Fix non IParasable object serialization.
13+
- Add basic support for serializing dictionary values in AdditionalData.
14+
1015
## [1.9.11] - 2024-07-22
1116

1217
- Obsoletes custom decompression handler in favor of native client capabilities.

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22
<!-- Common default project properties for ALL projects-->
33
<PropertyGroup>
4-
<VersionPrefix>1.9.11</VersionPrefix>
4+
<VersionPrefix>1.9.12</VersionPrefix>
55
<VersionSuffix></VersionSuffix>
66
<!-- This is overidden in test projects by setting to true-->
77
<IsTestProject>false</IsTestProject>

src/serialization/json/JsonSerializationWriter.cs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// ------------------------------------------------------------------------------
44

55
using System;
6+
using System.Collections;
67
using System.Collections.Generic;
78
using System.IO;
89
using System.Reflection;
@@ -344,7 +345,7 @@ public void WriteCollectionOfObjectValues<T>(string? key, IEnumerable<T>? values
344345
/// <param name="key">The key to be used for the written value. May be null.</param>
345346
/// <param name="values">The enum values to be written.</param>
346347
#if NET5_0_OR_GREATER
347-
public void WriteCollectionOfEnumValues<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]T>(string? key, IEnumerable<T?>? values) where T : struct, Enum
348+
public void WriteCollectionOfEnumValues<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>(string? key, IEnumerable<T?>? values) where T : struct, Enum
348349
#else
349350
public void WriteCollectionOfEnumValues<T>(string? key, IEnumerable<T?>? values) where T : struct, Enum
350351
#endif
@@ -360,6 +361,32 @@ public void WriteCollectionOfEnumValues<T>(string? key, IEnumerable<T?>? values)
360361
}
361362
}
362363
/// <summary>
364+
/// Writes the specified dictionary to the stream with an optional given key.
365+
/// </summary>
366+
/// <param name="key">The key to be used for the written value. May be null.</param>
367+
/// <param name="values">The dictionary of values to be written.</param>
368+
#if NET5_0_OR_GREATER
369+
private void WriteDictionaryValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>(string? key, T values) where T : IDictionary
370+
#else
371+
private void WriteDictionaryValue<T>(string? key, T values) where T : IDictionary
372+
#endif
373+
{
374+
if(values != null)
375+
{
376+
if(!string.IsNullOrEmpty(key))
377+
writer.WritePropertyName(key!);
378+
379+
writer.WriteStartObject();
380+
foreach(DictionaryEntry entry in values)
381+
{
382+
if(entry.Key is not string keyStr)
383+
throw new InvalidOperationException($"Error serializing dictionary value with key {key}, only string keyed dictionaries are supported.");
384+
WriteAnyValue(keyStr, entry.Value);
385+
}
386+
writer.WriteEndObject();
387+
}
388+
}
389+
/// <summary>
363390
/// Writes the specified byte array as a base64 string to the stream with an optional given key.
364391
/// </summary>
365392
/// <param name="key">The key to be used for the written value. May be null.</param>
@@ -433,7 +460,7 @@ public void WriteAdditionalData(IDictionary<string, object> value)
433460
}
434461

435462
#if NET5_0_OR_GREATER
436-
private void WriteNonParsableObjectValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(string? key,T value)
463+
private void WriteNonParsableObjectValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(string? key, T value)
437464
#else
438465
private void WriteNonParsableObjectValue<T>(string? key, T value)
439466
#endif
@@ -444,7 +471,7 @@ private void WriteNonParsableObjectValue<T>(string? key, T value)
444471
if(value == null)
445472
writer.WriteNullValue();
446473
else
447-
foreach(var oProp in typeof(T).GetProperties())
474+
foreach(var oProp in value.GetType().GetProperties())
448475
WriteAnyValue(oProp.Name, oProp.GetValue(value));
449476
writer.WriteEndObject();
450477
}
@@ -512,14 +539,17 @@ private void WriteAnyValue<T>(string? key, T value)
512539
writer.WritePropertyName(key!);
513540
jsonElement.WriteTo(writer);
514541
break;
542+
case IDictionary dictionary:
543+
WriteDictionaryValue(key, dictionary);
544+
break;
515545
case object o:
516546
WriteNonParsableObjectValue(key, o);
517547
break;
518548
case null:
519549
WriteNullValue(key);
520550
break;
521551
default:
522-
throw new InvalidOperationException($"error serialization additional data value with key {key}, unknown type {value?.GetType()}");
552+
throw new InvalidOperationException($"Error serializing additional data value with key {key}, unknown type {value?.GetType()}");
523553
}
524554
}
525555

tests/serialization/json/JsonSerializationWriterTests.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ public void WritesSampleObjectValue()
4141
{"businessPhones", new List<string>() {"+1 412 555 0109"}}, // write collection of primitives value
4242
{"endDateTime", new DateTime(2023,03,14,0,0,0,DateTimeKind.Utc) }, // ensure the DateTime doesn't crash
4343
{"manager", new TestEntity{Id = "48d31887-5fad-4d73-a9f5-3c356e68a038"}}, // write nested object value
44+
{"anonymousObject", new {Value1 = true, Value2 = "", Value3 = new List<string>{ "Value3.1", "Value3.2"}}}, // write nested object value
45+
{"dictionaryString", new Dictionary<string, string>{{"91bbe8e2-09b2-482b-a90e-00f8d7e81636", "b7992f48-a51b-41a1-ace5-4cebb7f111d0"}, { "ed64c116-2776-4012-94d1-a348b9d241bd", "55e1b4d0-2959-4c71-89b5-385ba5338a1c" }, }}, // write a Dictionary
46+
{"dictionaryTestEntity", new Dictionary<string, TestEntity>{{ "dd476fc9-7e97-4a4e-8d40-6c3de7432eb3", new TestEntity { Id = "dd476fc9-7e97-4a4e-8d40-6c3de7432eb3" } }, { "ffa5c351-7cf5-43df-9b55-e12455cf6eb2", new TestEntity { Id = "ffa5c351-7cf5-43df-9b55-e12455cf6eb2" } }, }}, // write a Dictionary
4447
}
4548
};
49+
4650
using var jsonSerializerWriter = new JsonSerializationWriter();
4751
// Act
4852
jsonSerializerWriter.WriteObjectValue(string.Empty, testEntity);
@@ -65,7 +69,10 @@ public void WritesSampleObjectValue()
6569
"\"weightInKgs\":51.80," +
6670
"\"businessPhones\":[\"\\u002B1 412 555 0109\"]," +
6771
"\"endDateTime\":\"2023-03-14T00:00:00+00:00\"," +
68-
"\"manager\":{\"id\":\"48d31887-5fad-4d73-a9f5-3c356e68a038\"}" +
72+
"\"manager\":{\"id\":\"48d31887-5fad-4d73-a9f5-3c356e68a038\"}," +
73+
"\"anonymousObject\":{\"Value1\":true,\"Value2\":\"\",\"Value3\":[\"Value3.1\",\"Value3.2\"]}," +
74+
"\"dictionaryString\":{\"91bbe8e2-09b2-482b-a90e-00f8d7e81636\":\"b7992f48-a51b-41a1-ace5-4cebb7f111d0\",\"ed64c116-2776-4012-94d1-a348b9d241bd\":\"55e1b4d0-2959-4c71-89b5-385ba5338a1c\"}," +
75+
"\"dictionaryTestEntity\":{\"dd476fc9-7e97-4a4e-8d40-6c3de7432eb3\":{\"id\":\"dd476fc9-7e97-4a4e-8d40-6c3de7432eb3\"},\"ffa5c351-7cf5-43df-9b55-e12455cf6eb2\":{\"id\":\"ffa5c351-7cf5-43df-9b55-e12455cf6eb2\"}}" +
6976
"}";
7077
Assert.Equal(expectedString, serializedJsonString);
7178
}
@@ -161,6 +168,24 @@ public void WritesSampleCollectionOfObjectValues()
161168
Assert.Equal(expectedString, serializedJsonString);
162169
}
163170

171+
[Fact]
172+
public void DoesntWriteUnsupportedTypes_NonStringKeyedDictionary()
173+
{
174+
// Arrange
175+
var testEntity = new TestEntity()
176+
{
177+
AdditionalData = new Dictionary<string, object>
178+
{
179+
{"nonStringKeyedDictionary", new Dictionary<int, string>{{ 1, "one" }, { 2, "two" }}}
180+
}
181+
};
182+
183+
using var jsonSerializerWriter = new JsonSerializationWriter();
184+
// Act & Assert
185+
var exception = Assert.Throws<InvalidOperationException>(() => jsonSerializerWriter.WriteObjectValue(string.Empty, testEntity));
186+
Assert.Equal("Error serializing dictionary value with key nonStringKeyedDictionary, only string keyed dictionaries are supported.", exception.Message);
187+
}
188+
164189
[Fact]
165190
public void WritesEnumValuesAsCamelCasedIfNotEscaped()
166191
{

0 commit comments

Comments
 (0)