Fork me on GitHub

Query for Raw JSON Edit on GitHub


Added in Marten v0.6 is the ability to retrieve just the raw JSON string for a document. The point is to be able to fetch the raw JSON from the database for a document and immediately stream that data to a web client without having to take the performance hit of deserializing and serializing the object to and from JSON.

As of v0.6, Marten supplies the IQuerySession/IDocumentSession.FindById<T>() mechanism as shown below:


[Fact]
public void when_find_then_a_json_should_be_returned()
{
    var issue = new Issue { Title = "Issue 1" };

    theSession.Store(issue);
    theSession.SaveChanges();

    var json = theSession.Json.FindById<Issue>(issue.Id);
    json.ShouldBe($"{{\"Id\": \"{issue.Id}\", \"Tags\": null, \"BugId\": null, \"Title\": \"Issue 1\", \"Number\": 0, \"AssigneeId\": null, \"ReporterId\": null}}");
}


There is also an asynchronous version:


[Fact]
public async Task when_find_then_a_json_should_be_returned()
{
    var issue = new Issue { Title = "Issue 2" };

    theSession.Store(issue);
    await theSession.SaveChangesAsync().ConfigureAwait(false);

    var json = await theSession.Json.FindByIdAsync<Issue>(issue.Id).ConfigureAwait(false);
    json.ShouldBe($"{{\"Id\": \"{issue.Id}\", \"Tags\": null, \"BugId\": null, \"Title\": \"Issue 2\", \"Number\": 0, \"AssigneeId\": null, \"ReporterId\": null}}");
}


As of v0.9, Marten supplies the following functionality to retrieve the raw JSON strings:


//[Fact]
public void when_get_json_then_raw_json_should_be_returned()
{
    var issue = new Issue { Title = "Issue 1" };

    theSession.Store(issue);
    theSession.SaveChanges();

    var json = theSession.Query<Issue>().Where(x => x.Title == "Issue 1").ToJsonArray();
    json.ShouldBe($"[{{\"Id\": \"{issue.Id}\", \"Tags\": null, \"Title\": \"Issue 1\", \"AssigneeId\": null, \"ReporterId\": null}}]");
    json = theSession.Query<Issue>().AsJson().First();
    json.ShouldBe($"{{\"Id\": \"{issue.Id}\", \"Tags\": null, \"Title\": \"Issue 1\", \"AssigneeId\": null, \"ReporterId\": null}}");
    json = theSession.Query<Issue>().AsJson().FirstOrDefault();
    json = theSession.Query<Issue>().AsJson().Single();
    json = theSession.Query<Issue>().AsJson().SingleOrDefault();
}

And the asynchronous version:


//[Fact]
public async Task when_get_json_then_raw_json_should_be_returned_async()
{
    var issue = new Issue { Title = "Issue 1" };

    theSession.Store(issue);
    theSession.SaveChanges();

    var json = await theSession.Query<Issue>().Where(x => x.Title == "Issue 1").ToJsonArrayAsync().ConfigureAwait(false);
    json.ShouldBe($"[{{\"Id\": \"{issue.Id}\", \"Tags\": null, \"Title\": \"Issue 1\", \"AssigneeId\": null, \"ReporterId\": null}}]");
    json = await theSession.Query<Issue>().AsJson().FirstAsync().ConfigureAwait(false);
    json.ShouldBe($"{{\"Id\": \"{issue.Id}\", \"Tags\": null, \"Title\": \"Issue 1\", \"AssigneeId\": null, \"ReporterId\": null}}");
    json = await theSession.Query<Issue>().AsJson().FirstOrDefaultAsync().ConfigureAwait(false);
    json = await theSession.Query<Issue>().AsJson().SingleAsync().ConfigureAwait(false);
    json = await theSession.Query<Issue>().AsJson().SingleOrDefaultAsync().ConfigureAwait(false);
}

Using AsJson() with Select() Transforms

New for Marten v0.9.1 is the ability to combine the AsJson() mechanics to the result of a Select() transform:


theSession
    .Query<User>()
    .OrderBy(x => x.FirstName)

    // Transform the User class to a different type
    .Select(x => new UserName { Name = x.FirstName })
    .AsJson()
    .First()
    .ShouldBe("{\"Name\": \"Bill\"}");

And another example, but this time transforming to an anonymous type:


theSession
    .Query<User>()
    .OrderBy(x => x.FirstName)

    // Transform to an anonymous type
    .Select(x => new { Name = x.FirstName })

    // Select only the raw JSON
    .AsJson()
    .FirstOrDefault()
    .ShouldBe("{\"Name\": \"Bill\"}");