using JsonRPC4.Common; using JsonRPC4.Router.Abstractions; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace JsonRPC4.Router.Defaults { public class DefaultRpcResponseSerializer : IRpcResponseSerializer { private IOptions serverConfig { get; } public DefaultRpcResponseSerializer(IOptions serverConfig) { this.serverConfig = serverConfig; } public Task SerializeBulkAsync(IEnumerable responses, Stream stream) { return SerializeInternalAsync(responses, isBulkRequest: true, stream); } public Task SerializeAsync(RpcResponse response, Stream stream) { return SerializeInternalAsync(new RpcResponse[1] { response }, isBulkRequest: false, stream); } private async Task SerializeInternalAsync(IEnumerable responses, bool isBulkRequest, Stream stream) { Utf8JsonWriter jsonWriter = (Utf8JsonWriter)(object)new Utf8JsonWriter(stream, default(JsonWriterOptions)); try { if (isBulkRequest) { jsonWriter.WriteStartArray(); foreach (RpcResponse response in responses) { SerializeResponse(response, jsonWriter); } jsonWriter.WriteEndArray(); } else { SerializeResponse(responses.Single(), jsonWriter); } } finally { await jsonWriter.FlushAsync(default(CancellationToken)); await jsonWriter.DisposeAsync(); } } private void SerializeResponse(RpcResponse response, Utf8JsonWriter jsonWriter) { jsonWriter.WriteStartObject(); jsonWriter.WritePropertyName("id"); switch (response.Id.Type) { case RpcIdType.Number: jsonWriter.WriteNumberValue(response.Id.NumberValue); break; case RpcIdType.String: jsonWriter.WriteStringValue(response.Id.StringValue); break; default: throw new NotImplementedException(); } jsonWriter.WriteString("jsonrpc", "2.0"); if (!response.HasError) { jsonWriter.WritePropertyName("result"); SerializeValue(response.Result, jsonWriter); } else { jsonWriter.WritePropertyName("error"); jsonWriter.WriteStartObject(); jsonWriter.WriteNumber("code", response.Error.Code); jsonWriter.WriteString("message", response.Error.Message); jsonWriter.WritePropertyName("data"); SerializeValue(response.Error.Data, jsonWriter); jsonWriter.WriteEndObject(); } jsonWriter.WriteEndObject(); } private void SerializeValue(object value, Utf8JsonWriter jsonWriter) { if (value != null) { JsonSerializerOptions jsonSerializerSettings = serverConfig.Value.JsonSerializerSettings; JsonDocument.Parse( JsonSerializer.SerializeToUtf8Bytes(value, value.GetType(), jsonSerializerSettings), default(JsonDocumentOptions)).WriteTo(jsonWriter); } else { jsonWriter.WriteNullValue(); } } } }