Merge pull request #3153 from crobibero/api-json-enum

Fix Json Enum conversion, map all JsonDefaults properties to API
pull/3232/head
Cody Robibero 4 years ago committed by GitHub
commit 93bca7ab50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,12 +1,12 @@
#nullable enable #nullable enable
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Models.ConfigurationDtos; using Jellyfin.Api.Models.ConfigurationDtos;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Serialization;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -23,22 +23,18 @@ namespace Jellyfin.Api.Controllers
{ {
private readonly IServerConfigurationManager _configurationManager; private readonly IServerConfigurationManager _configurationManager;
private readonly IMediaEncoder _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
private readonly IJsonSerializer _jsonSerializer;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ConfigurationController"/> class. /// Initializes a new instance of the <see cref="ConfigurationController"/> class.
/// </summary> /// </summary>
/// <param name="configurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="configurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
/// <param name="jsonSerializer">Instance of the <see cref="IJsonSerializer"/> interface.</param>
public ConfigurationController( public ConfigurationController(
IServerConfigurationManager configurationManager, IServerConfigurationManager configurationManager,
IMediaEncoder mediaEncoder, IMediaEncoder mediaEncoder)
IJsonSerializer jsonSerializer)
{ {
_configurationManager = configurationManager; _configurationManager = configurationManager;
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
_jsonSerializer = jsonSerializer;
} }
/// <summary> /// <summary>
@ -93,13 +89,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> UpdateNamedConfiguration([FromRoute] string key) public async Task<ActionResult> UpdateNamedConfiguration([FromRoute] string key)
{ {
var configurationType = _configurationManager.GetConfigurationType(key); var configurationType = _configurationManager.GetConfigurationType(key);
/*
// TODO switch to System.Text.Json when https://github.com/dotnet/runtime/issues/30255 is fixed.
var configuration = await JsonSerializer.DeserializeAsync(Request.Body, configurationType); var configuration = await JsonSerializer.DeserializeAsync(Request.Body, configurationType);
*/
var configuration = await _jsonSerializer.DeserializeFromStreamAsync(Request.Body, configurationType)
.ConfigureAwait(false);
_configurationManager.SaveConfiguration(key, configuration); _configurationManager.SaveConfiguration(key, configuration);
return Ok(); return Ok();
} }

@ -1,9 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.Json.Serialization;
using Jellyfin.Api; using Jellyfin.Api;
using Jellyfin.Api.Auth; using Jellyfin.Api.Auth;
using Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy; using Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy;
@ -11,6 +8,7 @@ using Jellyfin.Api.Auth.RequiresElevationPolicy;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Controllers; using Jellyfin.Api.Controllers;
using Jellyfin.Server.Formatters; using Jellyfin.Server.Formatters;
using MediaBrowser.Common.Json;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -83,8 +81,20 @@ namespace Jellyfin.Server.Extensions
.AddApplicationPart(typeof(StartupController).Assembly) .AddApplicationPart(typeof(StartupController).Assembly)
.AddJsonOptions(options => .AddJsonOptions(options =>
{ {
// Setting the naming policy to null leaves the property names as-is when serializing objects to JSON. // Update all properties that are set in JsonDefaults
options.JsonSerializerOptions.PropertyNamingPolicy = null; var jsonOptions = JsonDefaults.PascalCase;
// From JsonDefaults
options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling;
options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented;
options.JsonSerializerOptions.Converters.Clear();
foreach (var converter in jsonOptions.Converters)
{
options.JsonSerializerOptions.Converters.Add(converter);
}
// From JsonDefaults.PascalCase
options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy;
}) })
.AddControllersAsServices(); .AddControllersAsServices();
} }
@ -98,7 +108,7 @@ namespace Jellyfin.Server.Extensions
{ {
return serviceCollection.AddSwaggerGen(c => return serviceCollection.AddSwaggerGen(c =>
{ {
c.SwaggerDoc("api-docs", new OpenApiInfo { Title = "Jellyfin API" }); c.SwaggerDoc("api-docs", new OpenApiInfo { Title = "Jellyfin API", Version = "v1" });
// Add all xml doc files to swagger generator. // Add all xml doc files to swagger generator.
var xmlFiles = Directory.GetFiles( var xmlFiles = Directory.GetFiles(

@ -1,4 +1,4 @@
using Jellyfin.Server.Models; using MediaBrowser.Common.Json;
using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
@ -12,7 +12,7 @@ namespace Jellyfin.Server.Formatters
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CamelCaseJsonProfileFormatter"/> class. /// Initializes a new instance of the <see cref="CamelCaseJsonProfileFormatter"/> class.
/// </summary> /// </summary>
public CamelCaseJsonProfileFormatter() : base(JsonOptions.CamelCase) public CamelCaseJsonProfileFormatter() : base(JsonDefaults.CamelCase)
{ {
SupportedMediaTypes.Clear(); SupportedMediaTypes.Clear();
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json;profile=\"CamelCase\"")); SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json;profile=\"CamelCase\""));

@ -1,4 +1,4 @@
using Jellyfin.Server.Models; using MediaBrowser.Common.Json;
using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
@ -12,7 +12,7 @@ namespace Jellyfin.Server.Formatters
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="PascalCaseJsonProfileFormatter"/> class. /// Initializes a new instance of the <see cref="PascalCaseJsonProfileFormatter"/> class.
/// </summary> /// </summary>
public PascalCaseJsonProfileFormatter() : base(JsonOptions.PascalCase) public PascalCaseJsonProfileFormatter() : base(JsonDefaults.PascalCase)
{ {
SupportedMediaTypes.Clear(); SupportedMediaTypes.Clear();
// Add application/json for default formatter // Add application/json for default formatter

@ -1,41 +0,0 @@
using System.Text.Json;
namespace Jellyfin.Server.Models
{
/// <summary>
/// Json Options.
/// </summary>
public static class JsonOptions
{
/// <summary>
/// Gets CamelCase json options.
/// </summary>
public static JsonSerializerOptions CamelCase
{
get
{
var options = DefaultJsonOptions;
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
return options;
}
}
/// <summary>
/// Gets PascalCase json options.
/// </summary>
public static JsonSerializerOptions PascalCase
{
get
{
var options = DefaultJsonOptions;
options.PropertyNamingPolicy = null;
return options;
}
}
/// <summary>
/// Gets base Json Serializer Options.
/// </summary>
private static JsonSerializerOptions DefaultJsonOptions => new JsonSerializerOptions();
}
}

@ -12,10 +12,16 @@ namespace MediaBrowser.Common.Json
/// <summary> /// <summary>
/// Gets the default <see cref="JsonSerializerOptions" /> options. /// Gets the default <see cref="JsonSerializerOptions" /> options.
/// </summary> /// </summary>
/// <remarks>
/// When changing these options, update
/// Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
/// -> AddJellyfinApi
/// -> AddJsonOptions
/// </remarks>
/// <returns>The default <see cref="JsonSerializerOptions" /> options.</returns> /// <returns>The default <see cref="JsonSerializerOptions" /> options.</returns>
public static JsonSerializerOptions GetOptions() public static JsonSerializerOptions GetOptions()
{ {
var options = new JsonSerializerOptions() var options = new JsonSerializerOptions
{ {
ReadCommentHandling = JsonCommentHandling.Disallow, ReadCommentHandling = JsonCommentHandling.Disallow,
WriteIndented = false WriteIndented = false
@ -26,5 +32,31 @@ namespace MediaBrowser.Common.Json
return options; return options;
} }
/// <summary>
/// Gets CamelCase json options.
/// </summary>
public static JsonSerializerOptions CamelCase
{
get
{
var options = GetOptions();
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
return options;
}
}
/// <summary>
/// Gets PascalCase json options.
/// </summary>
public static JsonSerializerOptions PascalCase
{
get
{
var options = GetOptions();
options.PropertyNamingPolicy = null;
return options;
}
}
} }
} }

Loading…
Cancel
Save