Skip to content

Commit

Permalink
Merge pull request #382 from AArnott/fix377
Browse files Browse the repository at this point in the history
Use user-supplied JsonConverters when deserializing IProgress<T> report
  • Loading branch information
AArnott authored Nov 26, 2019
2 parents 197596a + 7a21a4b commit e0c9066
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 36 deletions.
34 changes: 20 additions & 14 deletions src/StreamJsonRpc.Tests/JsonRpcJsonHeadersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,6 @@ public JsonRpcJsonHeadersTests(ITestOutputHelper logger)
{
}

[Fact]
public async Task UnserializableTypeWorksWithConverter()
{
var clientMessageFormatter = (JsonMessageFormatter)this.clientMessageFormatter;
var serverMessageFormatter = (JsonMessageFormatter)this.serverMessageFormatter;

clientMessageFormatter.JsonSerializer.Converters.Add(new UnserializableTypeConverter());
serverMessageFormatter.JsonSerializer.Converters.Add(new UnserializableTypeConverter());
var result = await this.clientRpc.InvokeAsync<UnserializableType>(nameof(this.server.RepeatSpecialType), new UnserializableType { Value = "a" });
Assert.Equal("a!", result.Value);
}

[Fact]
public async Task CustomJsonConvertersAreNotAppliedToBaseMessage()
{
Expand Down Expand Up @@ -201,8 +189,8 @@ public async Task CanPassExceptionFromServer()

protected override void InitializeFormattersAndHandlers()
{
this.serverMessageFormatter = new JsonMessageFormatter();
this.clientMessageFormatter = new JsonMessageFormatter();
this.clientMessageFormatter = new JsonMessageFormatter { JsonSerializer = { Converters = { new UnserializableTypeConverter() } } };
this.serverMessageFormatter = new JsonMessageFormatter { JsonSerializer = { Converters = { new UnserializableTypeConverter() } } };

this.serverMessageHandler = new HeaderDelimitedMessageHandler(this.serverStream, this.serverStream, this.serverMessageFormatter);
this.clientMessageHandler = new HeaderDelimitedMessageHandler(this.clientStream, this.clientStream, this.clientMessageFormatter);
Expand All @@ -215,6 +203,24 @@ public class ParamsObjectWithCustomNames
public string? TheArgument { get; set; }
}

private class UnserializableTypeConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(CustomSerializedType);

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return new CustomSerializedType
{
Value = (string)reader.Value,
};
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((CustomSerializedType)value).Value);
}
}

private class StringBase64Converter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(string);
Expand Down
23 changes: 23 additions & 0 deletions src/StreamJsonRpc.Tests/JsonRpcMessagePackLengthTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MessagePack;
using MessagePack.Formatters;
using MessagePack.Resolvers;
using Microsoft.VisualStudio.Threading;
using StreamJsonRpc;
using StreamJsonRpc.Protocol;
Expand Down Expand Up @@ -57,7 +60,27 @@ protected override void InitializeFormattersAndHandlers()
this.serverMessageFormatter = new MessagePackFormatter();
this.clientMessageFormatter = new MessagePackFormatter();

var options = MessagePackSerializerOptions.Standard
.WithResolver(CompositeResolver.Create(
new IMessagePackFormatter[] { new UnserializableTypeFormatter() },
new IFormatterResolver[] { StandardResolverAllowPrivate.Instance }));
((MessagePackFormatter)this.serverMessageFormatter).SetMessagePackSerializerOptions(options);
((MessagePackFormatter)this.clientMessageFormatter).SetMessagePackSerializerOptions(options);

this.serverMessageHandler = new LengthHeaderMessageHandler(this.serverStream, this.serverStream, this.serverMessageFormatter);
this.clientMessageHandler = new LengthHeaderMessageHandler(this.clientStream, this.clientStream, this.clientMessageFormatter);
}

private class UnserializableTypeFormatter : IMessagePackFormatter<CustomSerializedType>
{
public CustomSerializedType Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return new CustomSerializedType { Value = reader.ReadString() };
}

public void Serialize(ref MessagePackWriter writer, CustomSerializedType value, MessagePackSerializerOptions options)
{
writer.Write(value?.Value);
}
}
}
49 changes: 28 additions & 21 deletions src/StreamJsonRpc.Tests/JsonRpcTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,24 @@ public async Task Invoke_MultipleProgressArguments()
Assert.True(progress2Reported);
}

[Fact]
public async Task CustomSerializedType_WorksWithConverter()
{
var result = await this.clientRpc.InvokeAsync<CustomSerializedType>(nameof(this.server.RepeatSpecialType), new CustomSerializedType { Value = "a" });
Assert.Equal("a!", result.Value);
}

[Fact]
public async Task ProgressOfT_WithCustomSerializedTypeArgument()
{
const string ExpectedResult = "hi!";
string? actualResult = null;
var progress = new ProgressWithCompletion<CustomSerializedType>(v => actualResult = v.Value);
await this.clientRpc.InvokeWithCancellationAsync(nameof(Server.RepeatSpecialType_ViaProgress), new object?[] { ExpectedResult.TrimEnd('!'), progress }, this.TimeoutToken);
await progress.WaitAsync(this.TimeoutToken);
Assert.Equal(ExpectedResult, actualResult);
}

[Fact]
public async Task CanInvokeServerMethodWithNoParameterPassedAsArray()
{
Expand Down Expand Up @@ -1919,9 +1937,14 @@ public void NotificationMethod(string arg)
this.notificationTcs.SetResult(arg);
}

public UnserializableType RepeatSpecialType(UnserializableType value)
public CustomSerializedType RepeatSpecialType(CustomSerializedType value)
{
return new CustomSerializedType { Value = value.Value + "!" };
}

public void RepeatSpecialType_ViaProgress(string value, IProgress<CustomSerializedType> progress)
{
return new UnserializableType { Value = value.Value + "!" };
progress?.Report(new CustomSerializedType { Value = value + "!" });
}

public string ExpectEncodedA(string arg)
Expand Down Expand Up @@ -2134,30 +2157,14 @@ public class Foo
public int Bazz { get; set; }
}

public class UnserializableType
public class CustomSerializedType
{
// Ignore this so default serializers will drop it, proving that custom serializers were used if the value propagates.
[JsonIgnore]
[IgnoreDataMember]
public string? Value { get; set; }
}

public class UnserializableTypeConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(UnserializableType);

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return new UnserializableType
{
Value = (string)reader.Value,
};
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((UnserializableType)value).Value);
}
}

[DataContract]
public class XAndYFields
{
Expand Down
2 changes: 1 addition & 1 deletion src/StreamJsonRpc/JsonMessageFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ private JsonRpcRequest ReadRequest(JToken json)
MessageFormatterProgressTracker.ProgressParamInformation? progressInfo = null;
if (this.formatterProgressTracker.TryGetProgressObject(progressId.Value<long>(), out progressInfo))
{
object? typedValue = value?.ToObject(progressInfo.ValueType);
object? typedValue = value?.ToObject(progressInfo.ValueType, this.JsonSerializer);
progressInfo.InvokeReport(typedValue);
}
}
Expand Down

0 comments on commit e0c9066

Please sign in to comment.