Composing and nesting with JsonApiDotNetCore
Tags: csharp, jsonapi, api, rest
Published: 2020-12-21 10:00:23

This is the final part of my three-part series on the release of [JsonApiDotNetCore](https://github.com/json-api-dotnet/JsonApiDotNetCore) 4.0! In our first post I showed you how to setup your API and in the second post I added relationships to the mix.

In this final post, lets dive deep and see some of the latest additions to the framework and what's coming next.

## Filters

One of the powerful new additions to the framework is the ability to have composable filters. Lets say we want to have all todo-items with a priority lower than 2. We can get those with the following request:

`GET /todoItems?filter=lessThan(priority,'2')` 

```json
{
  "links": {
    "self": "https://localhost:5001/todoItems?filter=lessThan(priority,'2')",
    "first": "https://localhost:5001/todoItems?filter=lessThan(priority,'2')"
  },
  "data": [
    {
      "type": "todoItems",
      "id": "1",
      "attributes": {
        "todo": "Make pizza",
        "priority": 1
      },
      "relationships": {
        "owner": {
          "links": {
            "self": "https://localhost:5001/todoItems/1/relationships/owner",
            "related": "https://localhost:5001/todoItems/1/owner"
          }
        }
      },
      "links": {
        "self": "https://localhost:5001/todoItems/1"
      }
    }
  ]
}
```

Previously I showed you how to include related resources, and the nice thing is, you can even apply filters on those! Lets see how we can get all people, along with their todo-items of first priority.

First, we need to include the related `todoItems`. Now we can apply the filter with the following request: 

`GET /people?include=todoItems&filter[todoItems]=equals(priority,'1')`.

This will give us the following payload, where we only see the todo-items with a priority of one.

```json
{
  "links": {
    "self": "https://localhost:5001/people?include=todoItems&filter[todoItems]=equals(priority,'1')",
    "first": "https://localhost:5001/people?include=todoItems&filter[todoItems]=equals(priority,'1')"
  },
  "data": [...],
  "included": [
    {
      "type": "todoItems",
      "id": "1",
      "attributes": {
        "todo": "Make pizza",
        "priority": 1
      },
      "relationships": {
        "owner": {
          "links": {
            "self": "https://localhost:5001/todoItems/1/relationships/owner",
            "related": "https://localhost:5001/todoItems/1/owner"
          }
        }
      },
      "links": {
        "self": "https://localhost:5001/todoItems/1"
      }
    }
  ]
}
```

We have now seen `lessThan` and `equals`, but there are more operators you can apply, like `contains`, `any` and even `not` to negate the filter. For a complete list, you can [read the filtering chapter in the documentation](https://www.jsonapi.net/usage/reading/filtering.html).

It becomes even more powerful when we combine multiple conditions together. If we wanted to have all todo's from people whose name starts with John *and* have a priority of one, we can make the following request:

`GET /todoItems?filter=and(startsWith(owner.name,'John'),equals(priority,'1'))`

All of the above is being translated to SQL and nothing is being evaluated in memory! This is done by building up a tree of expressions which are then translated into a LINQ query.

You can read more of the work behind the scenes in [this PR](https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/792). Magic...

Finally, the filtering on related resources is not only available on filters, but you get those as well for pagination, sorting and even sparse fieldsets. We could go crazy with a request like the following:

`GET /api/v1/blogs?include=articles.comments&page[number]=2,articles:3,articles.comments:4&page[size]=10,articles:5`

This returns at most 10 blogs at page 2. Per blog, it returns at most 5 included articles, all at page 3. Per blog, per article, returns included comments at page 4 using default page size. Mind blown yet?

## Conclusion

Although this blog series may have ended, the development on JsonApiDotNetCore has not.

Before I let you go, I would like to highlight an exciting new development called "[Atomic Operations](https://jsonapi.org/ext/atomic/)". This will allow you to send multiple changes, as a transaction, in a single request (on the streets people may call it batching) and thus reduce the amount of requests for making changes.

It's so powerful that it even allows you to establish relationships between operations within a single request, using something called local IDs. Work is progressing quickly on the [`atomic-operations` branch](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/atomic-operations). Check it out on Github if you want to follow along.

I hope you are as excited about JsonApiDotNetCore as I am! 

There is still a lot more to explore, for example check out the  [configuration options](https://www.jsonapi.net/usage/options.html), how you can [create or update resources with relationships](https://www.jsonapi.net/usage/writing/creating.html) or the amount of [extensibility you have at your proposal](https://www.jsonapi.net/usage/extensibility/layer-overview.html).

The 4.0 release is an amazing release which will delight all API clients out there. If you have any more questions, join the team on the [Gitter community](https://gitter.im/json-api-dotnet-core/Lobby) or start contributing on [Github](https://github.com/json-api-dotnet/JsonApiDotNetCore). And of course, you can reach out to me personally on Twitter under [@wunki](https://twitter.com/wunki).

Happy RESTing!