Skip to content

Newtonsoft serializer settings #720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions benchmarks/DependencyFactory.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using JsonApiDotNetCore.Builders;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Internal.Contracts;
using JsonApiDotNetCore.Models;
using JsonApiDotNetCore.Query;
Expand All @@ -9,9 +10,9 @@ namespace Benchmarks
{
internal static class DependencyFactory
{
public static IResourceGraph CreateResourceGraph()
public static IResourceGraph CreateResourceGraph(IJsonApiOptions options)
{
IResourceGraphBuilder builder = new ResourceGraphBuilder();
IResourceGraphBuilder builder = new ResourceGraphBuilder(options);
builder.AddResource<BenchmarkResource>(BenchmarkResourcePublicNames.Type);
return builder.Build();
}
Expand Down
10 changes: 5 additions & 5 deletions benchmarks/Query/QueryParserBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class QueryParserBenchmarks
public QueryParserBenchmarks()
{
IJsonApiOptions options = new JsonApiOptions();
IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph();
IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph(options);

var currentRequest = new CurrentRequest();
currentRequest.SetRequestResource(resourceGraph.GetResourceContext(typeof(BenchmarkResource)));
Expand Down Expand Up @@ -57,13 +57,13 @@ private static QueryParameterParser CreateQueryParameterDiscoveryForAll(IResourc
ISortService sortService = new SortService(resourceDefinitionProvider, resourceGraph, currentRequest);
ISparseFieldsService sparseFieldsService = new SparseFieldsService(resourceGraph, currentRequest);
IPageService pageService = new PageService(options, resourceGraph, currentRequest);
IOmitDefaultService omitDefaultService = new OmitDefaultService(options);
IOmitNullService omitNullService = new OmitNullService(options);
IDefaultsService defaultsService = new DefaultsService(options);
INullsService nullsService = new NullsService(options);

var queryServices = new List<IQueryParameterService>
{
includeService, filterService, sortService, sparseFieldsService, pageService, omitDefaultService,
omitNullService
includeService, filterService, sortService, sparseFieldsService, pageService, defaultsService,
nullsService
};

return new QueryParameterParser(options, queryStringAccessor, queryServices, NullLoggerFactory.Instance);
Expand Down
4 changes: 3 additions & 1 deletion benchmarks/Serialization/JsonApiDeserializerBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Internal.Contracts;
using JsonApiDotNetCore.Models;
using JsonApiDotNetCore.Serialization;
Expand Down Expand Up @@ -32,7 +33,8 @@ public class JsonApiDeserializerBenchmarks

public JsonApiDeserializerBenchmarks()
{
IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph();
var options = new JsonApiOptions();
IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph(options);
var targetedFields = new TargetedFields();

_jsonApiDeserializer = new RequestDeserializer(resourceGraph, targetedFields);
Expand Down
6 changes: 4 additions & 2 deletions benchmarks/Serialization/JsonApiSerializerBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using BenchmarkDotNet.Attributes;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Graph;
using JsonApiDotNetCore.Internal.Contracts;
using JsonApiDotNetCore.Managers;
Expand All @@ -24,7 +25,8 @@ public class JsonApiSerializerBenchmarks

public JsonApiSerializerBenchmarks()
{
IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph();
var options = new JsonApiOptions();
IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph(options);
IFieldsToSerialize fieldsToSerialize = CreateFieldsToSerialize(resourceGraph);

var metaBuilderMock = new Mock<IMetaBuilder<BenchmarkResource>>();
Expand All @@ -34,7 +36,7 @@ public JsonApiSerializerBenchmarks()
var resourceObjectBuilder = new ResourceObjectBuilder(resourceGraph, new ResourceObjectBuilderSettings());

_jsonApiSerializer = new ResponseSerializer<BenchmarkResource>(metaBuilderMock.Object, linkBuilderMock.Object,
includeBuilderMock.Object, fieldsToSerialize, resourceObjectBuilder, new CamelCaseFormatter());
includeBuilderMock.Object, fieldsToSerialize, resourceObjectBuilder, options);
}

private static FieldsToSerialize CreateFieldsToSerialize(IResourceGraph resourceGraph)
Expand Down
9 changes: 9 additions & 0 deletions src/Examples/JsonApiDotNetCoreExample/Models/Gender.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace JsonApiDotNetCoreExample.Models
{
public enum Gender
{
Unknown,
Male,
Female
}
}
5 changes: 4 additions & 1 deletion src/Examples/JsonApiDotNetCoreExample/Models/Person.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ public sealed class Person : Identifiable, IIsLockable
[Attr]
public string LastName { get; set; }

[Attr]
[Attr("the-Age")]
public int Age { get; set; }

[Attr]
public Gender Gender { get; set; }

[HasMany]
public List<TodoItem> TodoItems { get; set; }

Expand Down
24 changes: 24 additions & 0 deletions src/Examples/JsonApiDotNetCoreExample/Startups/KebabCaseStartup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using JsonApiDotNetCore.Configuration;
using Microsoft.AspNetCore.Hosting;
using Newtonsoft.Json.Serialization;

namespace JsonApiDotNetCoreExample
{
/// <summary>
/// This should be in JsonApiDotNetCoreExampleTests project but changes in .net core 3.0
/// do no longer allow that. See https://github.com/aspnet/AspNetCore/issues/15373.
/// </summary>
public sealed class KebabCaseStartup : Startup
{
public KebabCaseStartup(IWebHostEnvironment env) : base(env)
{
}

protected override void ConfigureJsonApiOptions(JsonApiOptions options)
{
base.ConfigureJsonApiOptions(options);

((DefaultContractResolver)options.SerializerSettings.ContractResolver).NamingStrategy = new KebabCaseNamingStrategy();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using JsonApiDotNetCoreExample.Data;
using Microsoft.EntityFrameworkCore;
using JsonApiDotNetCore.Extensions;
using System.Reflection;
using JsonApiDotNetCore.Configuration;

namespace JsonApiDotNetCoreExample
{
Expand All @@ -15,20 +11,11 @@ public sealed class NoDefaultPageSizeStartup : Startup
{
public NoDefaultPageSizeStartup(IWebHostEnvironment env) : base(env) { }

public override void ConfigureServices(IServiceCollection services)
protected override void ConfigureJsonApiOptions(JsonApiOptions options)
{
var mvcBuilder = services.AddMvcCore();
services
.AddDbContext<AppDbContext>(options => options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient)
.AddJsonApi(options => {
options.Namespace = "api/v1";
options.IncludeTotalRecordCount = true;
options.LoadDatabaseValues = true;
options.AllowClientGeneratedIds = true;
options.DefaultPageSize = 0;
},
discovery => discovery.AddAssembly(Assembly.Load(nameof(JsonApiDotNetCoreExample))),
mvcBuilder: mvcBuilder);
base.ConfigureJsonApiOptions(options);

options.DefaultPageSize = 0;
}
}
}
27 changes: 16 additions & 11 deletions src/Examples/JsonApiDotNetCoreExample/Startups/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
using Microsoft.EntityFrameworkCore;
using JsonApiDotNetCore.Extensions;
using System;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Query;
using JsonApiDotNetCoreExample.Services;
using Newtonsoft.Json.Converters;

namespace JsonApiDotNetCoreExample
{
Expand Down Expand Up @@ -37,21 +39,24 @@ public virtual void ConfigureServices(IServiceCollection services)
.EnableSensitiveDataLogging()
.UseNpgsql(GetDbConnectionString(), innerOptions => innerOptions.SetPostgresVersion(new Version(9,6)));
}, ServiceLifetime.Transient)
.AddJsonApi(options =>
{
options.IncludeExceptionStackTraceInErrors = true;
options.Namespace = "api/v1";
options.DefaultPageSize = 5;
options.IncludeTotalRecordCount = true;
options.LoadDatabaseValues = true;
options.ValidateModelState = true;
options.EnableResourceHooks = true;
},
discovery => discovery.AddCurrentAssembly());
.AddJsonApi(ConfigureJsonApiOptions, discovery => discovery.AddCurrentAssembly());

// once all tests have been moved to WebApplicationFactory format we can get rid of this line below
services.AddClientSerialization();
}

protected virtual void ConfigureJsonApiOptions(JsonApiOptions options)
{
options.IncludeExceptionStackTraceInErrors = true;
options.Namespace = "api/v1";
options.DefaultPageSize = 5;
options.IncludeTotalRecordCount = true;
options.LoadDatabaseValues = true;
options.ValidateModelState = true;
options.EnableResourceHooks = true;
options.SerializerSettings.Converters.Add(new StringEnumConverter());
}

public void Configure(
IApplicationBuilder app,
AppDbContext context)
Expand Down
4 changes: 0 additions & 4 deletions src/JsonApiDotNetCore/Builders/IResourceGraphBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using JsonApiDotNetCore.Graph;
using JsonApiDotNetCore.Internal;
using JsonApiDotNetCore.Internal.Contracts;
using JsonApiDotNetCore.Models;
Expand All @@ -19,7 +18,6 @@ public interface IResourceGraphBuilder
/// <param name="pluralizedTypeName">
/// The pluralized name that should be exposed by the API.
/// If nothing is specified, the configured name formatter will be used.
/// See <see cref="IResourceNameFormatter" />.
/// </param>
IResourceGraphBuilder AddResource<TResource>(string pluralizedTypeName = null) where TResource : class, IIdentifiable<int>;
/// <summary>
Expand All @@ -30,7 +28,6 @@ public interface IResourceGraphBuilder
/// <param name="pluralizedTypeName">
/// The pluralized name that should be exposed by the API.
/// If nothing is specified, the configured name formatter will be used.
/// See <see cref="IResourceNameFormatter" />.
/// </param>
IResourceGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName = null) where TResource : class, IIdentifiable<TId>;
/// <summary>
Expand All @@ -41,7 +38,6 @@ public interface IResourceGraphBuilder
/// <param name="pluralizedTypeName">
/// The pluralized name that should be exposed by the API.
/// If nothing is specified, the configured name formatter will be used.
/// See <see cref="IResourceNameFormatter" />.
/// </param>
IResourceGraphBuilder AddResource(Type entityType, Type idType, string pluralizedTypeName = null);
}
Expand Down
25 changes: 12 additions & 13 deletions src/JsonApiDotNetCore/Builders/JsonApiApplicationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace JsonApiDotNetCore.Builders
/// </summary>
public class JsonApiApplicationBuilder
{
public readonly JsonApiOptions JsonApiOptions = new JsonApiOptions();
private readonly JsonApiOptions _options = new JsonApiOptions();
internal IResourceGraphBuilder _resourceGraphBuilder;
internal bool _usesDbContext;
internal readonly IServiceCollection _services;
Expand All @@ -46,13 +46,13 @@ public JsonApiApplicationBuilder(IServiceCollection services, IMvcCoreBuilder mv
/// <summary>
/// Executes the action provided by the user to configure <see cref="JsonApiOptions"/>
/// </summary>
public void ConfigureJsonApiOptions(Action<JsonApiOptions> configureOptions) => configureOptions(JsonApiOptions);
public void ConfigureJsonApiOptions(Action<JsonApiOptions> configureOptions) => configureOptions(_options);

/// <summary>
/// Configures built-in .net core MVC (things like middleware, routing). Most of this configuration can be adjusted for the developers need.
/// Configures built-in .NET Core MVC (things like middleware, routing). Most of this configuration can be adjusted for the developers' need.
/// Before calling .AddJsonApi(), a developer can register their own implementation of the following services to customize startup:
/// <see cref="IResourceGraphBuilder"/>, <see cref="IServiceDiscoveryFacade"/>, <see cref="IJsonApiExceptionFilterProvider"/>,
/// <see cref="IJsonApiTypeMatchFilterProvider"/>, <see cref="IJsonApiRoutingConvention"/> and <see cref="IResourceNameFormatter"/>.
/// <see cref="IJsonApiTypeMatchFilterProvider"/> and <see cref="IJsonApiRoutingConvention"/>.
/// </summary>
public void ConfigureMvc()
{
Expand All @@ -76,7 +76,7 @@ public void ConfigureMvc()
options.Conventions.Insert(0, routingConvention);
});

if (JsonApiOptions.ValidateModelState)
if (_options.ValidateModelState)
{
_mvcBuilder.AddDataAnnotations();
}
Expand Down Expand Up @@ -144,7 +144,7 @@ public void ConfigureServices()
_services.AddScoped(typeof(IResourceQueryService<,>), typeof(DefaultResourceService<,>));
_services.AddScoped(typeof(IResourceCommandService<,>), typeof(DefaultResourceService<,>));

_services.AddSingleton<ILinksConfiguration>(JsonApiOptions);
_services.AddSingleton<ILinksConfiguration>(_options);
_services.AddSingleton(resourceGraph);
_services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
_services.AddSingleton<IResourceContextProvider>(resourceGraph);
Expand All @@ -165,7 +165,7 @@ public void ConfigureServices()

AddServerSerialization();
AddQueryParameterServices();
if (JsonApiOptions.EnableResourceHooks)
if (_options.EnableResourceHooks)
AddResourceHooks();

_services.AddScoped<IInverseRelationships, InverseRelationships>();
Expand All @@ -178,16 +178,16 @@ private void AddQueryParameterServices()
_services.AddScoped<ISortService, SortService>();
_services.AddScoped<ISparseFieldsService, SparseFieldsService>();
_services.AddScoped<IPageService, PageService>();
_services.AddScoped<IOmitDefaultService, OmitDefaultService>();
_services.AddScoped<IOmitNullService, OmitNullService>();
_services.AddScoped<IDefaultsService, DefaultsService>();
_services.AddScoped<INullsService, NullsService>();

_services.AddScoped<IQueryParameterService>(sp => sp.GetService<IIncludeService>());
_services.AddScoped<IQueryParameterService>(sp => sp.GetService<IFilterService>());
_services.AddScoped<IQueryParameterService>(sp => sp.GetService<ISortService>());
_services.AddScoped<IQueryParameterService>(sp => sp.GetService<ISparseFieldsService>());
_services.AddScoped<IQueryParameterService>(sp => sp.GetService<IPageService>());
_services.AddScoped<IQueryParameterService>(sp => sp.GetService<IOmitDefaultService>());
_services.AddScoped<IQueryParameterService>(sp => sp.GetService<IOmitNullService>());
_services.AddScoped<IQueryParameterService>(sp => sp.GetService<IDefaultsService>());
_services.AddScoped<IQueryParameterService>(sp => sp.GetService<INullsService>());
}

private void AddResourceHooks()
Expand All @@ -214,8 +214,7 @@ private void AddServerSerialization()

private void RegisterJsonApiStartupServices()
{
_services.AddSingleton<IJsonApiOptions>(JsonApiOptions);
_services.TryAddSingleton<IResourceNameFormatter>(new CamelCaseFormatter());
_services.AddSingleton<IJsonApiOptions>(_options);
_services.TryAddSingleton<IJsonApiRoutingConvention, DefaultRoutingConvention>();
_services.TryAddSingleton<IResourceGraphBuilder, ResourceGraphBuilder>();
_services.TryAddSingleton<IServiceDiscoveryFacade>(sp => new ServiceDiscoveryFacade(_services, sp.GetRequiredService<IResourceGraphBuilder>()));
Expand Down
Loading