Version 1.0 removes the MediatR and Newtonsoft.Json dependencies. It replaces the public request and pipeline contracts with equivalent contracts owned by OmniSharp.Extensions.JsonRpc and uses System.Text.Json for arbitrary JSON values.
Remove a direct MediatR package reference if your application used it only for this library. The OmniSharp packages no longer reference or configure MediatR.
Likewise, remove a direct Newtonsoft.Json package reference if it was needed only for OmniSharp protocol models. Keep it if other application code still uses Newtonsoft.Json.
Protocol models now use System.Text.Json instead of Newtonsoft.Json. Add the appropriate imports when working with arbitrary JSON values:
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
+using System.Text.Json.Nodes;The affected public types are:
| 0.19.x | 1.0 |
|---|---|
LSPAny.Value: JToken? |
LSPAny.Value: JsonElement |
LSPObject : JObject |
LSPObject, wrapping a JsonObject in Value |
LSPArray : JArray |
LSPArray, wrapping a JsonArray in Value |
Use JsonElement APIs such as ValueKind, TryGetProperty, GetProperty, EnumerateArray, and the typed Get* methods:
-JToken value = request.Data.Value;
-string? name = (string?)value["name"];
-foreach (JToken item in value["items"] ?? new JArray())
+JsonElement value = request.Data.Value;
+string? name = value.TryGetProperty("name", out var nameProperty)
+ ? nameProperty.GetString()
+ : null;
+
+if (value.TryGetProperty("items", out var items))
{
- Console.WriteLine((string?)item);
+ foreach (JsonElement item in items.EnumerateArray())
+ {
+ Console.WriteLine(item.GetString());
+ }
}LSPAny clones incoming JsonElement values, so its Value does not depend on the lifetime of the JsonDocument from which the element originated. Create arbitrary protocol values with LSPAny.From:
var data = LSPAny.From(new
{
name = "example",
enabled = true
});LSPObject and LSPArray are no longer subclasses of the Newtonsoft LINQ-to-JSON types. Construct them directly or work with their mutable Value properties:
var payload = new LSPObject
{
["name"] = "example",
["items"] = new LSPArray(1, "two", false)
};
JsonObject jsonObject = payload.Value;
JsonArray jsonArray = new LSPArray(1, 2, 3).Value;
LSPAny data = LSPAny.From(payload);LSPObject retains a string indexer, but it returns JsonNode? rather than JToken?. LSPArray does not inherit collection APIs; use its Value property for indexing, enumeration, and mutation:
var values = new LSPArray("first", "second");
values.Value[0] = "updated";
foreach (JsonNode? value in values.Value)
{
Console.WriteLine(value?.ToJsonString());
}Both wrappers have a one-way implicit conversion to JsonNode. That conversion returns a deep clone, so mutating the converted node does not mutate the wrapper:
JsonNode clonedNode = payload;There is no implicit conversion from JsonNode, JsonObject, or JsonArray back to an LSP wrapper. Use LSPAny.From(node) when an arbitrary protocol value is sufficient, or populate a new LSPObject/LSPArray when the wrapper type is required.
Replace the MediatR import in handlers, request models, and pipeline behaviors:
-using MediatR;
+using OmniSharp.Extensions.JsonRpc;The following contract names and behavior remain available from the new namespace:
| 0.19.x | 1.0 |
|---|---|
MediatR.IRequest<TResponse> |
OmniSharp.Extensions.JsonRpc.IRequest<TResponse> |
MediatR.IRequest |
OmniSharp.Extensions.JsonRpc.IRequest |
MediatR.IRequestHandler<TRequest, TResponse> |
OmniSharp.Extensions.JsonRpc.IRequestHandler<TRequest, TResponse> |
MediatR.IRequestHandler<TRequest> |
OmniSharp.Extensions.JsonRpc.IRequestHandler<TRequest> |
MediatR.IPipelineBehavior<TRequest, TResponse> |
OmniSharp.Extensions.JsonRpc.IPipelineBehavior<TRequest, TResponse> |
MediatR.RequestHandlerDelegate<TResponse> |
OmniSharp.Extensions.JsonRpc.RequestHandlerDelegate<TResponse> |
MediatR.Unit |
OmniSharp.Extensions.JsonRpc.Unit |
Generated LSP and DAP handler interfaces now inherit the JSON-RPC-owned handler contracts. Existing handler method signatures remain the same after changing the namespace import.
using OmniSharp.Extensions.JsonRpc;
public sealed class HoverHandler : IHoverHandler
{
public Task<Hover?> Handle(HoverParams request, CancellationToken cancellationToken)
{
return Task.FromResult<Hover?>(null);
}
}Code that implemented a handler through an explicitly qualified MediatR interface must instead implement the generated handler interface or the corresponding OmniSharp.Extensions.JsonRpc.IRequestHandler<,> interface.
Change custom pipeline behavior registrations and implementations to the JSON-RPC-owned interface. Open-generic dependency injection registrations keep the same shape:
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));Pipeline behavior ordering, cancellation-token forwarding, and nested next delegate execution are unchanged.
Notification and no-result request handlers now return OmniSharp.Extensions.JsonRpc.Unit. If a file also uses System.Reactive.Unit, add aliases to make the intended type explicit:
using JsonRpcUnit = OmniSharp.Extensions.JsonRpc.Unit;
using ReactiveUnit = System.Reactive.Unit;Incoming requests are dispatched directly to the handler selected by the JSON-RPC descriptor. Request scopes, pipeline behavior composition, cancellation, notification fan-out, aggregate responses, and exception mapping retain their 0.19.x behavior.