Skip to content

Examples

Aghogho Bernard edited this page May 12, 2026 · 1 revision

Examples

A tour of the patterns you'll most often need.

1. Direct property matching

When JSON keys already match your C# properties:

public class Product
{
    public int Id { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
}

var json = await httpClient.GetStringAsync("https://api.example.com/products");
var products = new List<Product>();

json.MapCollection(products, options =>
{
    options.RootKey = "products";
});

2. Custom name mapping

When JSON uses different names than your model:

// JSON: { "data": [{ "product_name": "Widget", "unit_price": 9.99 }] }

json.MapCollection(products, options =>
{
    options.RootKey = "data";
    options.Mappings = new Dictionary<string, string>
    {
        { "Title", "product_name" },
        { "Price", "unit_price" }
    };
});

You only need to declare the differences. Properties whose names already match (case-insensitive) are picked up automatically.

3. Nested JSON paths

Dot notation works for both RootKey and Mappings values:

{
  "response": {
    "data": {
      "employees": [
        {
          "name": "Alice",
          "work": {
            "department": "Engineering",
            "manager": { "email": "bob@example.com" }
          }
        }
      ]
    }
  }
}
json.MapCollection(employees, options =>
{
    options.RootKey = "response.data.employees";
    options.Mappings = new Dictionary<string, string>
    {
        { "Department",   "work.department" },
        { "ManagerEmail", "work.manager.email" }
    };
});

4. Updating an existing collection

Pre-populated lists (e.g. fetched from your DB) get matched by ItemKey:

var products = LoadProductsFromDatabase();

freshJson.MapCollection(products, options =>
{
    options.RootKey = "products";
    options.ItemKey = "Sku";
    options.Mappings = new Dictionary<string, string>
    {
        { "Price",       "unit_price" },
        { "Description", "details.summary" }
    };
});

Each existing product is matched to a JSON row whose Sku matches, and only the mapped properties are updated. Unmatched products are left untouched. New JSON rows without a corresponding existing product are not added.

5. ItemKey when names differ

If your ItemKey is in Mappings, the mapper uses the mapped JSON path to find the value:

// JSON: [{ "product_name": "Widget", "price": 9.99 }]
// C# property: Title (no JSON key called "Title")

options.ItemKey = "Title";                      // C# property name
options.Mappings = new()
{
    { "Title", "product_name" },                // JSON uses product_name
    { "Price", "price" }
};

The lookup uses product_name from JSON but matches against the Title property in your existing items.

6. Custom emptiness predicate (IsItemEmpty)

When the default ItemKey-is-empty rule doesn't fit your domain:

var profiles = LoadDraftProfiles();

json.MapCollection(profiles, options =>
{
    options.RootKey = "employees";
    options.ItemKey = "EmployeeId";
    options.IsItemEmpty = item =>
    {
        var p = (EmployeeProfile)item;
        // "Empty" = not yet finalized AND missing identifier
        return !p.IsFinalized && string.IsNullOrEmpty(p.EmployeeId);
    };
    options.Mappings = new()
    {
        { "EmployeeId", "id" },
        { "FullName",   "displayName" }
    };
});

If every existing profile passes the predicate, the mapper enters Create Mode and rebuilds the list. If any profile fails it, the mapper enters Update Mode.

7. Mixed default + custom mapping

You only need Mappings entries for properties whose JSON names differ from your C# names. Other properties are mapped by direct name automatically.

public class Order
{
    public int Id { get; set; }                       // matches "Id" / "id" automatically
    public string Status { get; set; }                // matches "Status" / "status" automatically
    public decimal TotalAmount { get; set; }          // needs mapping below
}

options.Mappings = new()
{
    { "TotalAmount", "total" }                        // only the one that differs
};

8. Re-using a destination list across calls

When polling an API for updates, you can keep one list and refresh it on each call:

var products = new List<Product>();

while (running)
{
    var json = await httpClient.GetStringAsync(apiUrl);
    json.MapCollection(products, options =>
    {
        options.RootKey = "products";
        options.ItemKey = "Sku";
        options.Mappings = new() { { "Price", "unit_price" } };
    });

    // products list now has the latest prices for items it already knew about.
    // New JSON rows are *not* added — handle that separately if you need it.
    await Task.Delay(TimeSpan.FromMinutes(1));
}

Clone this wiki locally