JSON-RPC Request Builder — C# source
Build valid JSON-RPC 2.0 requests, notifications, success responses, and error responses, plus batch arrays. Validate message structure.
This is the C# implementation — the same logic the interactive tool runs, in a shareable, citable form.
// json-rpc-builder — C# port: JSON-RPC 2.0 message builder + structural validation.
using System.Text.Json;
using System.Text.Json.Nodes;
var req = BuildRequest("getBalance", 1, JsonValue.Create(new[] { "0x1234" }), hasParams: true);
Console.WriteLine(req.Json);
Console.WriteLine(BuildNotification("blockHeader").Json);
Console.WriteLine(BuildSuccessResponse(1, "0x1bc16d674ec80000").Json);
Console.WriteLine(BuildErrorResponse(1, -32601).Json);
var (valid, problems) = Validate(JsonSerializer.Deserialize<JsonObject>(@"{""jsonrpc"":""1.0""}"));
Console.WriteLine($"{valid}: {string.Join("; ", problems)}");
record Outcome(bool Ok, string Json, string? Error = null);
static string? StandardError(int code) => code switch {
-32700 => "Parse error", -32600 => "Invalid Request", -32601 => "Method not found",
-32602 => "Invalid params", -32603 => "Internal error", -32000 => "Server error",
_ => null,
};
// JsonObject preserves insertion order, so key order matches the TS lib.
static string Stringify(JsonNode node, int? indent = null) =>
node.ToJsonString(indent is > 0
? new JsonSerializerOptions { WriteIndented = true } // 2-space pretty print
: null);
// `hasParams` tells "absent" apart from a real JSON null — the C# analog of the
// TS lib's unset sentinel (optional reference parameters cannot).
static Outcome BuildRequest(string method, JsonNode? id, JsonNode? @params = null,
bool hasParams = false, int? indent = null) {
if (string.IsNullOrEmpty(method))
return new Outcome(false, "", "method must be a non-empty string");
var o = new JsonObject { ["jsonrpc"] = "2.0", ["method"] = method };
if (hasParams) o["params"] = @params;
o["id"] = id;
return new Outcome(true, Stringify(o, indent));
}
// A notification is a request without an id: fire-and-forget, no reply.
static Outcome BuildNotification(string method, JsonNode? @params = null,
bool hasParams = false, int? indent = null) {
if (string.IsNullOrEmpty(method))
return new Outcome(false, "", "method must be a non-empty string");
var o = new JsonObject { ["jsonrpc"] = "2.0", ["method"] = method };
if (hasParams) o["params"] = @params;
return new Outcome(true, Stringify(o, indent));
}
static Outcome BuildSuccessResponse(JsonNode? id, JsonNode? result, int? indent = null) {
var o = new JsonObject { ["jsonrpc"] = "2.0", ["result"] = result, ["id"] = id };
return new Outcome(true, Stringify(o, indent));
}
static Outcome BuildErrorResponse(JsonNode? id, int code, string? message = null,
JsonNode? data = null, bool hasData = false,
int? indent = null) {
var err = new JsonObject { ["code"] = code, ["message"] = message ?? StandardError(code) ?? "Error" };
if (hasData) err["data"] = data;
var o = new JsonObject { ["jsonrpc"] = "2.0", ["error"] = err, ["id"] = id };
return new Outcome(true, Stringify(o, indent));
}
// Lightweight shape check — reports every problem, not just the first.
static (bool Valid, List<string> Errors) Validate(JsonObject? o) {
if (o is null) return (false, new List<string> { "Not an object." });
var errors = new List<string>();
if (o["jsonrpc"]?.GetValue<string>() != "2.0") errors.Add("jsonrpc must be \"2.0\".");
if (o.ContainsKey("method") && o["method"]!.GetValue<JsonElement>().ValueKind != JsonValueKind.String)
errors.Add("method must be a string.");
if (o.ContainsKey("result") && o.ContainsKey("error"))
errors.Add("cannot have both result and error.");
if (!o.ContainsKey("method") && !o.ContainsKey("result") && !o.ContainsKey("error"))
errors.Add("must have method, result, or error.");
return (errors.Count == 0, errors);
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →