Suppose, your class Book contains some JSON field 'Data'. The structure of 'Data' can be changed between restarts but is known prior to any start (i.e. you know both property names and their types at the startup).
The following code addresses that case:
using System.Linq;
using HotChocolate.Resolvers;
using HotChocolate.Types;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Linq;
namespace Ademchenko.GraphQLWorkshop
{
public class Book
{
public int Id { get; set; }
public JObject Data { get; set; }
}
public interface IBookService { IQueryable<Book> GetAll(); }
public class InMemoryBookService : IBookService
{
private readonly Book[] _staticBooks = {
new Book {Id = 11, Data = JObject.FromObject(new {Title = "FooBook", AuthorId = 1, Price = 10.2m})},
new Book {Id = 22, Data = JObject.FromObject(new { Title = "BarBook", AuthorId = 2, Price = 20.2m})}
};
public IQueryable<Book> GetAll() => _staticBooks.AsQueryable();
}
public class Query
{
public IQueryable<Book> GetBooks(IResolverContext ctx) => ctx.Service<IBookService>().GetAll();
}
public class BookType : ObjectType<Book>
{
protected override void Configure(IObjectTypeDescriptor<Book> descriptor)
{
descriptor.Field(d => d.Data).Type<DataType>();
}
}
public class DataType : ObjectType
{
protected override void Configure(IObjectTypeDescriptor descriptor)
{
descriptor.Field("title").Type<StringType>().Resolve((ctx, ct) => (string)ctx.Parent<JObject>()["Title"]);
descriptor.Field("authorId").Type<IntType>().Resolve((ctx, ct) => (int)ctx.Parent<JObject>()["AuthorId"]);
descriptor.Field("price").Type<DecimalType>().Resolve((ctx, ct) => (decimal)ctx.Parent<JObject>()["AuthorId"]);
}
}
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration) => Configuration = configuration;
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<IBookService, InMemoryBookService>();
services.AddGraphQLServer()
.AddQueryType<Query>()
.AddType<BookType>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) => app.UseRouting().UseEndpoints(endpoints => endpoints.MapGraphQL());
}
}
Making the request to the server:
{
books
{
id,
data
{
title
authorId
price
}
}
}
you will get the following response:
{
"data": {
"books": [
{
"id": 11,
"data": {
"title": "FooBook",
"authorId": 1,
"price": 1
}
},
{
"id": 22,
"data": {
"title": "BarBook",
"authorId": 2,
"price": 2
}
}
]
}
}