2.18Sending from JSON

Updated on Aug 20, 2026~18 min read

The framework also supports initiating an HTTP request from a JSON configuration string in one step, completely replacing traditional chained calls. Simply organize the request parameters into JSON format, pass them to the HttpRequestBuilder.FromJson() method, and then send via IHttpRemoteService.

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://furion.net",            "method": "GET"        }        """));

Complete JSON Syntax Reference

The following table lists all available JSON fields (property names are case-insensitive, and trailing commas are supported):

Field (Primary Key)AliasesTypeRequiredDescription
methodstringNoThe request method (GET, POST, PUT, DELETE, PATCH, etc.). If not specified, it is automatically inferred based on whether a request body is included: POST when a body is present, otherwise GET.
urlrequestUristringYesThe request address. Supports absolute URIs (such as https://api.furion.net) or relative paths (such as /api/data). Relative paths can be used together with baseURL.
baseURLbaseAddress, baseUrlstringNoThe request base address. Must be an absolute URI. When url is a relative path, the two are combined into a complete address according to the rules.
headersobjectNoA dictionary of request headers. Keys are header names and values are header values (strings). For example {"Accept": "application/json", "X-API-Key": "xxx"}.
paramsqueries, query, queryParametersobjectNoURL query parameters. They are automatically appended after the ? in the request address. For example {"page": 1, "size": 10}?page=1&size=10.
cookiesobjectNoA Cookies dictionary. For example {"session": "abc", "user": "john"}.
timeoutnumberNoThe timeout duration (in milliseconds). For example 5000 means 5 seconds.
clientclientName, httpClientNamestringNoThe name of a client registered in IHttpClientFactory. Used to select a specific HttpClient instance.
httpVersionversionstringNoThe HTTP version. Supports "1.0", "1.1", "2.0", "3.0", etc.
authauthentication, authorizationobjectNoAuthentication configuration. Must include a type field ("bearer", "basic", or "digest").
Bearer example: {"type": "bearer", "token": "xxx"}, with an optional "header" custom header name (default Authorization).
Basic example: {"type": "basic", "username": "user", "password": "pass"}.
Digest example: {"type": "digest", "username": "user", "password": "secret"}.
dataanyNoThe request body content. Can be a JSON object, string, number, etc. The framework passes the JsonNode as raw content, and the Content-Type is ultimately inferred by the content processor.
contentTypestringNoUsed together with data to explicitly specify Content-Type. If not specified, the framework automatically infers it from the actual type of data (for example, a JSON object is inferred as application/json).
encodingstringNoUsed together with data to specify the content encoding (such as "utf-8"). If not specified, the default encoding is used.
multipartobjectNoMultipart form (multipart/form-data) content. Each property of the object represents a form item.
Regular field: "name": "John" → a text field.
File field: "file": "@C:\\path\\to\\file.jpg" or "@https://example.com/file.png" (a network file).
Supports the @file;type=mime/type and @file;filename=renamed.txt syntaxes.
Multiple file upload: "files": ["@file1.jpg", "@file2.jpg"] (array form, same field name).
profilerdebuggerbooleanNoWhether to enable the request profiler. true enables it, false disables it.

Note: When method is not specified, the framework automatically infers it based on whether data or multipart is present: POST when present, otherwise GET.

A Regular GET Request

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://furion.net",            "method": "GET"        }        """));

With Query Parameters and a JSON Request Body

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://localhost:7044/HttpRemote/AddModel",            "method": "POST",            "queries": {                "query1": 10,                "query2": "hello"            },            "headers": {                "Content-Type": "application/json"            },            "data": {                "id": 1,                "name": "sample"            }        }        """));

Multipart Form (File Upload + Regular Fields)

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://localhost:7044/HttpRemote/AddForm",            "method": "POST",            "queries": {                "id": 100            },            "multipart": {                "Id": 100,                "Name": "furion",                "File": "@C:\\Workspaces\\httptest.jpg"            }        }        """));

File field values start with @ and support local absolute paths or network URLs (such as "@https://example.com/avatar.png"). Extended syntaxes such as @path;type=image/png and @path;filename=photo.jpg are also supported.

URL-Encoded Form

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://localhost:7044/HttpRemote/AddUrlForm",            "method": "POST",            "headers": {                "Content-Type": "application/x-www-form-urlencoded"            },            "data": "id=200&name=furion"        }        """));

Or serialize automatically through an object (which requires explicitly specifying contentType):

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://localhost:7044/HttpRemote/AddUrlForm",            "method": "POST",            "data": {                "id": 200,                "name": "fu rion"            },            "contentType": "application/x-www-form-urlencoded"        }        """));

Single File Upload

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://localhost:7044/HttpRemote/AddFile",            "method": "POST",            "multipart": {                "file": "@C:\\Workspaces\\httptest.jpg"            }        }        """));

Multiple File Upload

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://localhost:7044/HttpRemote/AddFiles",            "method": "POST",            "multipart": {                "files": ["@C:\\Workspaces\\file1.jpg", "@C:\\Workspaces\\file2.jpg"]            }        }        """));

Sending a Raw String

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://localhost:7044/HttpRemote/RawString",            "method": "POST",            "headers": {                "Content-Type": "application/json"            },            "data": "\"This is a raw string\""        }        """));

Request with Authentication Information

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://jsonplaceholder.typicode.com/posts",            "method": "POST",            "headers": {                "Content-Type": "application/json"            },            "auth": {                "type": "basic",                "username": "testuser",                "password": "testpass"            },            "data": {                "title": "Test"            }        }        """));

Specifying Timeout and HTTP Version

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://httpbin.org/delay/3",            "method": "GET",            "timeout": 5000,            "httpVersion": "2.0"        }        """));

Enabling the Request Profiler

cs
var result = await httpRemoteService.SendAsStringAsync(    HttpRequestBuilder.FromJson("""        {            "url": "https://furion.net",            "method": "GET",            "profiler": true        }        """));

Extending a Custom JSON Extractor

Similar to the cURL parser, JSON parsing also uses a pluggable extractor architecture. Each JSON field is handled by an IHttpJsonExtractor implementation. You can add custom extractors to support private fields (such as "customField") without modifying the framework source code.

Implementing a Custom Extractor

The most convenient approach is to inherit from the HttpJsonExtractorBase abstract base class, which already encapsulates the property-name and alias matching logic:

cs
using HttpAgent;/// <summary>///     Custom json.customField extractor/// </summary>internal sealed class JsonCustomFieldExtractor : HttpJsonExtractorBase{    /// <summary>    ///     Primary property name    /// </summary>    protected override string PropertyName => "customField";    /// <summary>    ///     Optional alias list    /// </summary>    protected override string[]? Aliases => ["custom", "custom_field"];    /// <summary>    ///     Concrete operation executed when a property is matched    /// </summary>    protected override void Extract(HttpRequestBuilder httpRequestBuilder, JsonNode node,        HttpJsonParsingContext context)    {        // Set the builder according to the node value here        if (node is JsonValue jsonValue && jsonValue.TryGetValue<string>(out var value))        {            httpRequestBuilder.WithHeader("X-Custom-Field", value);        }    }}

For more complex scenarios, you can directly implement the IHttpJsonExtractor interface and manually iterate over the root JsonObject.

Registering a Custom Extractor

Inject it through the configuration delegate when calling FromJson:

cs
var builder = HttpRequestBuilder.FromJson("""    {        "url":"http://example.com",        "method":"GET",        "customField":"hello"    }    """,    options => options.AddExtractor(new JsonCustomFieldExtractor()));

To remove a built-in extractor, use options.RemoveExtractor<T>(). For example:

cs
var builder = HttpRequestBuilder.FromJson("""    {        "url":"http://example.com"    }    """,    options => options.RemoveExtractor<JsonMethodExtractor>());

Context Object Description

HttpJsonParsingContext provides safe access methods for the root JsonObject:

MemberDescription
RootObjectGets the root JsonObject
TryGetNode(propertyName, out node)Safely gets the JsonNode with the specified property name; returns false if it does not exist
GetNode(propertyName)Gets the JsonNode with the specified property name; returns null if it does not exist
ContainsProperty(propertyName)Checks whether the root object contains the specified property

Reference Implementation

All extractors built into the framework (such as JsonMethodExtractor, JsonMultipartExtractor, and so on) are built on the same base class and interface. You can view their source code in the repository as a reference: View built-in JSON extractor source code