mirror of
https://github.com/Sarsoo/Spotify.NET.git
synced 2024-12-24 23:16:28 +00:00
adding System.Text.Json serialiser with source generators
This commit is contained in:
parent
c0f514d2a4
commit
94f4435ad4
@ -15,7 +15,7 @@ namespace SpotifyAPI.Web
|
|||||||
|
|
||||||
Assert.IsInstanceOf(typeof(SimplePaginator), defaultConfig.DefaultPaginator);
|
Assert.IsInstanceOf(typeof(SimplePaginator), defaultConfig.DefaultPaginator);
|
||||||
Assert.IsInstanceOf(typeof(NetHttpClient), defaultConfig.HTTPClient);
|
Assert.IsInstanceOf(typeof(NetHttpClient), defaultConfig.HTTPClient);
|
||||||
Assert.IsInstanceOf(typeof(NewtonsoftJSONSerializer), defaultConfig.JSONSerializer);
|
Assert.IsInstanceOf(typeof(TextJsonSerializer), defaultConfig.JSONSerializer);
|
||||||
Assert.AreEqual(SpotifyUrls.APIV1, defaultConfig.BaseAddress);
|
Assert.AreEqual(SpotifyUrls.APIV1, defaultConfig.BaseAddress);
|
||||||
Assert.AreEqual(null, defaultConfig.Authenticator);
|
Assert.AreEqual(null, defaultConfig.Authenticator);
|
||||||
Assert.AreEqual(null, defaultConfig.HTTPLogger);
|
Assert.AreEqual(null, defaultConfig.HTTPLogger);
|
||||||
@ -32,7 +32,7 @@ namespace SpotifyAPI.Web
|
|||||||
|
|
||||||
Assert.IsInstanceOf(typeof(SimplePaginator), defaultConfig.DefaultPaginator);
|
Assert.IsInstanceOf(typeof(SimplePaginator), defaultConfig.DefaultPaginator);
|
||||||
Assert.IsInstanceOf(typeof(NetHttpClient), defaultConfig.HTTPClient);
|
Assert.IsInstanceOf(typeof(NetHttpClient), defaultConfig.HTTPClient);
|
||||||
Assert.IsInstanceOf(typeof(NewtonsoftJSONSerializer), defaultConfig.JSONSerializer);
|
Assert.IsInstanceOf(typeof(TextJsonSerializer), defaultConfig.JSONSerializer);
|
||||||
Assert.AreEqual(SpotifyUrls.APIV1, defaultConfig.BaseAddress);
|
Assert.AreEqual(SpotifyUrls.APIV1, defaultConfig.BaseAddress);
|
||||||
Assert.AreEqual(null, defaultConfig.HTTPLogger);
|
Assert.AreEqual(null, defaultConfig.HTTPLogger);
|
||||||
Assert.AreEqual(null, defaultConfig.RetryHandler);
|
Assert.AreEqual(null, defaultConfig.RetryHandler);
|
||||||
|
15
SpotifyAPI.Web.Tests/Http/ExampleResponses.cs
Normal file
15
SpotifyAPI.Web.Tests/Http/ExampleResponses.cs
Normal file
File diff suppressed because one or more lines are too long
@ -5,6 +5,8 @@ using Moq;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using SpotifyAPI.Web.Http;
|
using SpotifyAPI.Web.Http;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace SpotifyAPI.Web.Tests
|
namespace SpotifyAPI.Web.Tests
|
||||||
{
|
{
|
||||||
@ -82,9 +84,60 @@ namespace SpotifyAPI.Web.Tests
|
|||||||
Assert.AreEqual(apiResonse.Response, response.Object);
|
Assert.AreEqual(apiResonse.Response, response.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TestResponseObject
|
[TestCase]
|
||||||
|
public async Task DeserializeResponse_TimeCurrentlyPlayingTestMessage()
|
||||||
{
|
{
|
||||||
public bool HelloWorld { get; set; }
|
var serializer = new NewtonsoftJSONSerializer();
|
||||||
|
var response = new Mock<IResponse>();
|
||||||
|
response.SetupGet(r => r.Body).Returns(ExampleResponses.CurrentlyPlayingContext);
|
||||||
|
response.SetupGet(r => r.ContentType).Returns("application/json");
|
||||||
|
|
||||||
|
var times = new List<long>();
|
||||||
|
foreach (var iter in Enumerable.Range(0, 50))
|
||||||
|
{
|
||||||
|
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
|
||||||
|
IAPIResponse<CurrentlyPlayingContext> apiResonse = serializer.DeserializeResponse<CurrentlyPlayingContext>(response.Object);
|
||||||
|
|
||||||
|
watch.Stop();
|
||||||
|
times.Add(watch.ElapsedMilliseconds);
|
||||||
|
|
||||||
|
Assert.AreEqual(apiResonse.Response, response.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mean = times.Sum() / 50;
|
||||||
|
|
||||||
|
using StreamWriter file = new("newtonsoft.json_test.txt", append: true);
|
||||||
|
await file.WriteLineAsync($"CurrentlyPlayingContext: {mean}ms");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase]
|
||||||
|
public async Task DeserializeResponse_TimeUserTestMessage()
|
||||||
|
{
|
||||||
|
var serializer = new NewtonsoftJSONSerializer();
|
||||||
|
var response = new Mock<IResponse>();
|
||||||
|
response.SetupGet(r => r.Body).Returns(ExampleResponses.PublicUser);
|
||||||
|
response.SetupGet(r => r.ContentType).Returns("application/json");
|
||||||
|
|
||||||
|
var times = new List<long>();
|
||||||
|
foreach (var iter in Enumerable.Range(0, 50))
|
||||||
|
{
|
||||||
|
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
|
||||||
|
IAPIResponse<PublicUser> apiResonse = serializer.DeserializeResponse<PublicUser>(response.Object);
|
||||||
|
|
||||||
|
watch.Stop();
|
||||||
|
times.Add(watch.ElapsedMilliseconds);
|
||||||
|
|
||||||
|
Assert.AreEqual(apiResonse.Response, response.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mean = times.Sum() / 50;
|
||||||
|
|
||||||
|
using StreamWriter file = new("newtonsoft.json_test.txt", append: true);
|
||||||
|
await file.WriteLineAsync($"User: {mean}ms");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
134
SpotifyAPI.Web.Tests/Http/SystemTextTests.cs
Normal file
134
SpotifyAPI.Web.Tests/Http/SystemTextTests.cs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using SpotifyAPI.Web.Http;
|
||||||
|
|
||||||
|
namespace SpotifyAPI.Web.Tests
|
||||||
|
{
|
||||||
|
public class SystemTextTests
|
||||||
|
{
|
||||||
|
public static IEnumerable<object> DontSerializeTestSource
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return new TestCaseData(null);
|
||||||
|
yield return new TestCaseData("string");
|
||||||
|
yield return new TestCaseData(new MemoryStream(Encoding.UTF8.GetBytes("string")));
|
||||||
|
yield return new TestCaseData(new StringContent("string"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCaseSource(nameof(DontSerializeTestSource))]
|
||||||
|
public void SerializeRequest_SkipsAlreadySerialized(object input)
|
||||||
|
{
|
||||||
|
var serializer = new TextJsonSerializer();
|
||||||
|
var request = new Mock<IRequest>();
|
||||||
|
request.SetupGet(r => r.Body).Returns(input);
|
||||||
|
|
||||||
|
serializer.SerializeRequest(request.Object);
|
||||||
|
|
||||||
|
Assert.AreEqual(input, request.Object.Body);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase]
|
||||||
|
public void DeserializeResponse_SkipsNonJson()
|
||||||
|
{
|
||||||
|
var serializer = new TextJsonSerializer();
|
||||||
|
var response = new Mock<IResponse>();
|
||||||
|
response.SetupGet(r => r.Body).Returns("hello");
|
||||||
|
response.SetupGet(r => r.ContentType).Returns("media/mp4");
|
||||||
|
|
||||||
|
IAPIResponse<object> apiResonse = serializer.DeserializeResponse<object>(response.Object);
|
||||||
|
Assert.AreEqual(apiResonse.Body, null);
|
||||||
|
Assert.AreEqual(apiResonse.Response, response.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase]
|
||||||
|
public void DeserializeResponse_HandlesJson()
|
||||||
|
{
|
||||||
|
var serializer = new TextJsonSerializer();
|
||||||
|
var response = new Mock<IResponse>();
|
||||||
|
response.SetupGet(r => r.Body).Returns("{\"hello_world\": false}");
|
||||||
|
response.SetupGet(r => r.ContentType).Returns("application/json");
|
||||||
|
|
||||||
|
IAPIResponse<TestResponseObject> apiResonse = serializer.DeserializeResponse<TestResponseObject>(response.Object);
|
||||||
|
Assert.AreEqual(apiResonse.Body?.HelloWorld, false);
|
||||||
|
Assert.AreEqual(apiResonse.Response, response.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase]
|
||||||
|
public void DeserializeResponse_TestMessage()
|
||||||
|
{
|
||||||
|
var serializer = new TextJsonSerializer();
|
||||||
|
var response = new Mock<IResponse>();
|
||||||
|
response.SetupGet(r => r.Body).Returns(ExampleResponses.CurrentlyPlayingContext);
|
||||||
|
response.SetupGet(r => r.ContentType).Returns("application/json");
|
||||||
|
|
||||||
|
IAPIResponse<CurrentlyPlayingContext> apiResonse = serializer.DeserializeResponse<CurrentlyPlayingContext>(response.Object);
|
||||||
|
|
||||||
|
Assert.AreEqual(apiResonse.Response, response.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase]
|
||||||
|
public async Task DeserializeResponse_TimeCurrentlyPlayingTestMessage()
|
||||||
|
{
|
||||||
|
var serializer = new TextJsonSerializer();
|
||||||
|
var response = new Mock<IResponse>();
|
||||||
|
response.SetupGet(r => r.Body).Returns(ExampleResponses.CurrentlyPlayingContext);
|
||||||
|
response.SetupGet(r => r.ContentType).Returns("application/json");
|
||||||
|
|
||||||
|
var times = new List<long>();
|
||||||
|
foreach(var iter in Enumerable.Range(0, 50))
|
||||||
|
{
|
||||||
|
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
|
||||||
|
IAPIResponse<CurrentlyPlayingContext> apiResonse = serializer.DeserializeResponse<CurrentlyPlayingContext>(response.Object);
|
||||||
|
|
||||||
|
watch.Stop();
|
||||||
|
times.Add(watch.ElapsedMilliseconds);
|
||||||
|
|
||||||
|
Assert.AreEqual(apiResonse.Response, response.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mean = times.Sum() / 50;
|
||||||
|
|
||||||
|
using StreamWriter file = new("system.text.json_test.txt", append: true);
|
||||||
|
await file.WriteLineAsync($"CurrentlyPlayingContext: {mean}ms");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase]
|
||||||
|
public async Task DeserializeResponse_TimeUserTestMessage()
|
||||||
|
{
|
||||||
|
var serializer = new TextJsonSerializer();
|
||||||
|
var response = new Mock<IResponse>();
|
||||||
|
response.SetupGet(r => r.Body).Returns(ExampleResponses.PublicUser);
|
||||||
|
response.SetupGet(r => r.ContentType).Returns("application/json");
|
||||||
|
|
||||||
|
var times = new List<long>();
|
||||||
|
foreach (var iter in Enumerable.Range(0, 50))
|
||||||
|
{
|
||||||
|
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
|
||||||
|
IAPIResponse<PublicUser> apiResonse = serializer.DeserializeResponse<PublicUser>(response.Object);
|
||||||
|
|
||||||
|
watch.Stop();
|
||||||
|
times.Add(watch.ElapsedMilliseconds);
|
||||||
|
|
||||||
|
Assert.AreEqual(apiResonse.Response, response.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mean = times.Sum() / 50;
|
||||||
|
|
||||||
|
using StreamWriter file = new("system.text.json_test.txt", append: true);
|
||||||
|
await file.WriteLineAsync($"User: {mean}ms");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@
|
|||||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||||
<PackageReference Include="NUnit.Console" Version="3.13.0" />
|
<PackageReference Include="NUnit.Console" Version="3.13.0" />
|
||||||
|
<PackageReference Include="System.IO" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -38,7 +38,7 @@ namespace SpotifyAPI.Web
|
|||||||
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-playlists-tracks
|
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-playlists-tracks
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Paging<PlaylistTrack<IPlayableItem>>> GetItems(string playlistId);
|
Task<Paging<PlaylistTrack<BasePlayableItem>>> GetItems(string playlistId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get full details of the items of a playlist owned by a Spotify user.
|
/// Get full details of the items of a playlist owned by a Spotify user.
|
||||||
@ -49,7 +49,7 @@ namespace SpotifyAPI.Web
|
|||||||
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-playlists-tracks
|
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-playlists-tracks
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Paging<PlaylistTrack<IPlayableItem>>> GetItems(string playlistId, PlaylistGetItemsRequest request);
|
Task<Paging<PlaylistTrack<BasePlayableItem>>> GetItems(string playlistId, PlaylistGetItemsRequest request);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a playlist for a Spotify user. (The playlist will be empty until you add tracks.)
|
/// Create a playlist for a Spotify user. (The playlist will be empty until you add tracks.)
|
||||||
|
@ -26,19 +26,19 @@ namespace SpotifyAPI.Web
|
|||||||
return API.Post<SnapshotResponse>(URLs.PlaylistTracks(playlistId), null, request.BuildBodyParams());
|
return API.Post<SnapshotResponse>(URLs.PlaylistTracks(playlistId), null, request.BuildBodyParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Paging<PlaylistTrack<IPlayableItem>>> GetItems(string playlistId)
|
public Task<Paging<PlaylistTrack<BasePlayableItem>>> GetItems(string playlistId)
|
||||||
{
|
{
|
||||||
var request = new PlaylistGetItemsRequest();
|
var request = new PlaylistGetItemsRequest();
|
||||||
|
|
||||||
return GetItems(playlistId, request);
|
return GetItems(playlistId, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Paging<PlaylistTrack<IPlayableItem>>> GetItems(string playlistId, PlaylistGetItemsRequest request)
|
public Task<Paging<PlaylistTrack<BasePlayableItem>>> GetItems(string playlistId, PlaylistGetItemsRequest request)
|
||||||
{
|
{
|
||||||
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
|
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
|
||||||
Ensure.ArgumentNotNull(request, nameof(request));
|
Ensure.ArgumentNotNull(request, nameof(request));
|
||||||
|
|
||||||
return API.Get<Paging<PlaylistTrack<IPlayableItem>>>(URLs.PlaylistTracks(playlistId), request.BuildQueryParams());
|
return API.Get<Paging<PlaylistTrack<BasePlayableItem>>>(URLs.PlaylistTracks(playlistId), request.BuildQueryParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<FullPlaylist> Create(string userId, PlaylistCreateRequest request)
|
public Task<FullPlaylist> Create(string userId, PlaylistCreateRequest request)
|
||||||
|
@ -187,7 +187,7 @@ namespace SpotifyAPI.Web
|
|||||||
return new SpotifyClientConfig(
|
return new SpotifyClientConfig(
|
||||||
SpotifyUrls.APIV1,
|
SpotifyUrls.APIV1,
|
||||||
null,
|
null,
|
||||||
new NewtonsoftJSONSerializer(),
|
new TextJsonSerializer(),
|
||||||
new NetHttpClient(),
|
new NetHttpClient(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
@ -18,7 +18,7 @@ namespace SpotifyAPI.Web.Http
|
|||||||
public event EventHandler<IResponse>? ResponseReceived;
|
public event EventHandler<IResponse>? ResponseReceived;
|
||||||
|
|
||||||
public APIConnector(Uri baseAddress, IAuthenticator authenticator) :
|
public APIConnector(Uri baseAddress, IAuthenticator authenticator) :
|
||||||
this(baseAddress, authenticator, new NewtonsoftJSONSerializer(), new NetHttpClient(), null, null)
|
this(baseAddress, authenticator, new TextJsonSerializer(), new NetHttpClient(), null, null)
|
||||||
{ }
|
{ }
|
||||||
public APIConnector(
|
public APIConnector(
|
||||||
Uri baseAddress,
|
Uri baseAddress,
|
||||||
|
93
SpotifyAPI.Web/Http/TextJsonSerializer.cs
Normal file
93
SpotifyAPI.Web/Http/TextJsonSerializer.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.Json.Serialization.Metadata;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace SpotifyAPI.Web.Http
|
||||||
|
{
|
||||||
|
public class SnakeCase : JsonNamingPolicy
|
||||||
|
{
|
||||||
|
public override string ConvertName(string name)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
return Regex.Replace(string.Concat(name[0].ToString().ToLowerInvariant(), name.Substring(1)), "[A-Z]", "_$0").ToLowerInvariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TextJsonSerializer : IJSONSerializer
|
||||||
|
{
|
||||||
|
private ModelJsonContext JsonContext;
|
||||||
|
|
||||||
|
public TextJsonSerializer()
|
||||||
|
{
|
||||||
|
JsonContext = ModelJsonContext.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAPIResponse<T> DeserializeResponse<T>(IResponse response)
|
||||||
|
{
|
||||||
|
Ensure.ArgumentNotNull(response, nameof(response));
|
||||||
|
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
response.ContentType?.Equals("application/json", StringComparison.Ordinal) is true || response.ContentType == null
|
||||||
|
))
|
||||||
|
{
|
||||||
|
if(response.Body is string bodyString && !string.IsNullOrWhiteSpace(bodyString))
|
||||||
|
{
|
||||||
|
var body = (T?)JsonSerializer.Deserialize(response.Body as string ?? "", typeof(T), JsonContext);
|
||||||
|
|
||||||
|
// In order to work out whether track or episode has been returned, first deserialise as BasePlayableItem
|
||||||
|
// which has enum of current playing type, then deserialise again with concrete playing type
|
||||||
|
if (body is CurrentlyPlaying currentlyPlaying)
|
||||||
|
{
|
||||||
|
if(currentlyPlaying.Item.Type is ItemType.Track)
|
||||||
|
{
|
||||||
|
body = (T?) JsonSerializer.Deserialize(response.Body as string ?? "", typeof(CurrentlyPlaying<FullTrack>), JsonContext);
|
||||||
|
}
|
||||||
|
else if (currentlyPlaying.Item.Type is ItemType.Episode)
|
||||||
|
{
|
||||||
|
body = (T?) JsonSerializer.Deserialize(response.Body as string ?? "", typeof(CurrentlyPlaying<FullEpisode>), JsonContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (body is CurrentlyPlayingContext currentlyPlayingContext)
|
||||||
|
{
|
||||||
|
if (currentlyPlayingContext.Item.Type is ItemType.Track)
|
||||||
|
{
|
||||||
|
body = (T?)JsonSerializer.Deserialize(response.Body as string ?? "", typeof(CurrentlyPlayingContext<FullTrack>), JsonContext);
|
||||||
|
}
|
||||||
|
else if (currentlyPlayingContext.Item.Type is ItemType.Episode)
|
||||||
|
{
|
||||||
|
body = (T?)JsonSerializer.Deserialize(response.Body as string ?? "", typeof(CurrentlyPlayingContext<FullEpisode>), JsonContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new APIResponse<T>(response, body!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new APIResponse<T>(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SerializeRequest(IRequest request)
|
||||||
|
{
|
||||||
|
Ensure.ArgumentNotNull(request, nameof(request));
|
||||||
|
|
||||||
|
if (request.Body is string || request.Body is Stream || request.Body is HttpContent || request.Body is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Body = JsonSerializer.Serialize(request.Body, request.Body.GetType(), JsonContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
SpotifyAPI.Web/Models/ModelJsonContext.cs
Normal file
88
SpotifyAPI.Web/Models/ModelJsonContext.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using SpotifyAPI.Web.Http;
|
||||||
|
|
||||||
|
namespace SpotifyAPI.Web
|
||||||
|
{
|
||||||
|
[JsonSerializable(typeof(Actions))]
|
||||||
|
[JsonSerializable(typeof(AlbumsResponse))]
|
||||||
|
[JsonSerializable(typeof(ArtistsRelatedArtistsResponse))]
|
||||||
|
[JsonSerializable(typeof(ArtistsResponse))]
|
||||||
|
[JsonSerializable(typeof(ArtistsTopTracksResponse))]
|
||||||
|
[JsonSerializable(typeof(AuthorizationCodeRefreshResponse))]
|
||||||
|
[JsonSerializable(typeof(AuthorizationCodeTokenResponse))]
|
||||||
|
[JsonSerializable(typeof(CategoriesResponse))]
|
||||||
|
[JsonSerializable(typeof(Category))]
|
||||||
|
[JsonSerializable(typeof(CategoryPlaylistsResponse))]
|
||||||
|
[JsonSerializable(typeof(ClientCredentialsTokenResponse))]
|
||||||
|
[JsonSerializable(typeof(Context))]
|
||||||
|
[JsonSerializable(typeof(Copyright))]
|
||||||
|
[JsonSerializable(typeof(CurrentlyPlaying))]
|
||||||
|
[JsonSerializable(typeof(CurrentlyPlaying<FullEpisode>))]
|
||||||
|
[JsonSerializable(typeof(CurrentlyPlaying<FullTrack>))]
|
||||||
|
[JsonSerializable(typeof(CurrentlyPlayingContext))]
|
||||||
|
[JsonSerializable(typeof(CurrentlyPlayingContext<FullEpisode>))]
|
||||||
|
[JsonSerializable(typeof(CurrentlyPlayingContext<FullTrack>))]
|
||||||
|
[JsonSerializable(typeof(Cursor))]
|
||||||
|
[JsonSerializable(typeof(Device))]
|
||||||
|
[JsonSerializable(typeof(DeviceResponse))]
|
||||||
|
[JsonSerializable(typeof(EpisodesResponse))]
|
||||||
|
[JsonSerializable(typeof(FeaturedPlaylistsResponse))]
|
||||||
|
[JsonSerializable(typeof(FollowedArtistsResponse))]
|
||||||
|
[JsonSerializable(typeof(Followers))]
|
||||||
|
[JsonSerializable(typeof(FullAlbum))]
|
||||||
|
[JsonSerializable(typeof(FullEpisode))]
|
||||||
|
[JsonSerializable(typeof(FullPlaylist))]
|
||||||
|
[JsonSerializable(typeof(FullShow))]
|
||||||
|
[JsonSerializable(typeof(FullTrack))]
|
||||||
|
[JsonSerializable(typeof(Image))]
|
||||||
|
[JsonSerializable(typeof(LinkedTrack))]
|
||||||
|
[JsonSerializable(typeof(NewReleasesResponse))]
|
||||||
|
[JsonSerializable(typeof(PKCETokenResponse))]
|
||||||
|
[JsonSerializable(typeof(PlayHistoryItem))]
|
||||||
|
[JsonSerializable(typeof(PlaylistTrack<FullTrack>))]
|
||||||
|
[JsonSerializable(typeof(PlaylistTrack<FullEpisode>))]
|
||||||
|
[JsonSerializable(typeof(PrivateUser))]
|
||||||
|
[JsonSerializable(typeof(PublicUser))]
|
||||||
|
[JsonSerializable(typeof(RecommendationGenresResponse))]
|
||||||
|
[JsonSerializable(typeof(RecommendationSeed))]
|
||||||
|
[JsonSerializable(typeof(RecommendationsResponse))]
|
||||||
|
[JsonSerializable(typeof(ResumePoint))]
|
||||||
|
[JsonSerializable(typeof(SavedAlbum))]
|
||||||
|
[JsonSerializable(typeof(SavedEpisodes))]
|
||||||
|
[JsonSerializable(typeof(SavedShow))]
|
||||||
|
[JsonSerializable(typeof(SavedTrack))]
|
||||||
|
[JsonSerializable(typeof(SearchResponse))]
|
||||||
|
[JsonSerializable(typeof(Section))]
|
||||||
|
[JsonSerializable(typeof(Segment))]
|
||||||
|
[JsonSerializable(typeof(ShowsResponse))]
|
||||||
|
[JsonSerializable(typeof(SimpleAlbum))]
|
||||||
|
[JsonSerializable(typeof(SimpleArtist))]
|
||||||
|
[JsonSerializable(typeof(SimpleEpisode))]
|
||||||
|
[JsonSerializable(typeof(SimplePlaylist))]
|
||||||
|
[JsonSerializable(typeof(SimpleShow))]
|
||||||
|
[JsonSerializable(typeof(SimpleTrack))]
|
||||||
|
[JsonSerializable(typeof(SnapshotResponse))]
|
||||||
|
[JsonSerializable(typeof(TestResponseObject))]
|
||||||
|
[JsonSerializable(typeof(TimeInterval))]
|
||||||
|
[JsonSerializable(typeof(TrackAudio))]
|
||||||
|
[JsonSerializable(typeof(TrackAudioAnalysis))]
|
||||||
|
[JsonSerializable(typeof(TrackMeta))]
|
||||||
|
[JsonSerializable(typeof(TracksAudioFeaturesResponse))]
|
||||||
|
[JsonSerializable(typeof(TracksResponse))]
|
||||||
|
public partial class ModelJsonContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
public static ModelJsonContext Get()
|
||||||
|
{
|
||||||
|
return new ModelJsonContext(new JsonSerializerOptions()
|
||||||
|
{
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||||
|
PropertyNamingPolicy = new SnakeCase(),
|
||||||
|
Converters =
|
||||||
|
{
|
||||||
|
new JsonStringEnumConverter()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,10 +9,10 @@ namespace SpotifyAPI.Web
|
|||||||
Episode
|
Episode
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IPlayableItem
|
public class BasePlayableItem
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
ItemType Type { get; }
|
public ItemType Type { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13,9 +13,17 @@ namespace SpotifyAPI.Web
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value></value>
|
/// <value></value>
|
||||||
[JsonConverter(typeof(PlayableItemConverter))]
|
[JsonConverter(typeof(PlayableItemConverter))]
|
||||||
public IPlayableItem Item { get; set; } = default!;
|
public BasePlayableItem Item { get; set; } = default!;
|
||||||
public int? ProgressMs { get; set; }
|
public int? ProgressMs { get; set; }
|
||||||
public long Timestamp { get; set; }
|
public long Timestamp { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CurrentlyPlaying<T>: CurrentlyPlaying where T : BasePlayableItem
|
||||||
|
{
|
||||||
|
public new T Item {
|
||||||
|
get => (T) base.Item;
|
||||||
|
set => base.Item = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,10 +17,19 @@ namespace SpotifyAPI.Web
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value></value>
|
/// <value></value>
|
||||||
[JsonConverter(typeof(PlayableItemConverter))]
|
[JsonConverter(typeof(PlayableItemConverter))]
|
||||||
public IPlayableItem Item { get; set; } = default!;
|
public BasePlayableItem Item { get; set; } = default!;
|
||||||
|
|
||||||
public string CurrentlyPlayingType { get; set; } = default!;
|
public string CurrentlyPlayingType { get; set; } = default!;
|
||||||
public Actions Actions { get; set; } = default!;
|
public Actions Actions { get; set; } = default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CurrentlyPlayingContext<T> : CurrentlyPlayingContext where T : BasePlayableItem
|
||||||
|
{
|
||||||
|
public new T Item
|
||||||
|
{
|
||||||
|
get => (T)base.Item;
|
||||||
|
set => base.Item = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ using Newtonsoft.Json.Converters;
|
|||||||
|
|
||||||
namespace SpotifyAPI.Web
|
namespace SpotifyAPI.Web
|
||||||
{
|
{
|
||||||
public class FullEpisode : IPlayableItem
|
public class FullEpisode : BasePlayableItem
|
||||||
{
|
{
|
||||||
public string AudioPreviewUrl { get; set; } = default!;
|
public string AudioPreviewUrl { get; set; } = default!;
|
||||||
public string Description { get; set; } = default!;
|
public string Description { get; set; } = default!;
|
||||||
|
@ -19,7 +19,7 @@ namespace SpotifyAPI.Web
|
|||||||
/// A list of PlaylistTracks, which items can be a FullTrack or FullEpisode
|
/// A list of PlaylistTracks, which items can be a FullTrack or FullEpisode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value></value>
|
/// <value></value>
|
||||||
public Paging<PlaylistTrack<IPlayableItem>>? Tracks { get; set; } = default!;
|
public Paging<PlaylistTrack<BasePlayableItem>>? Tracks { get; set; } = default!;
|
||||||
public string? Type { get; set; } = default!;
|
public string? Type { get; set; } = default!;
|
||||||
public string? Uri { get; set; } = default!;
|
public string? Uri { get; set; } = default!;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ using Newtonsoft.Json.Converters;
|
|||||||
|
|
||||||
namespace SpotifyAPI.Web
|
namespace SpotifyAPI.Web
|
||||||
{
|
{
|
||||||
public class FullTrack : IPlayableItem
|
public class FullTrack : BasePlayableItem
|
||||||
{
|
{
|
||||||
public SimpleAlbum Album { get; set; } = default!;
|
public SimpleAlbum Album { get; set; } = default!;
|
||||||
public List<SimpleArtist> Artists { get; set; } = default!;
|
public List<SimpleArtist> Artists { get; set; } = default!;
|
||||||
|
@ -2,8 +2,8 @@ namespace SpotifyAPI.Web
|
|||||||
{
|
{
|
||||||
public class Image
|
public class Image
|
||||||
{
|
{
|
||||||
public int Height { get; set; }
|
public int? Height { get; set; }
|
||||||
public int Width { get; set; }
|
public int? Width { get; set; }
|
||||||
public string Url { get; set; } = default!;
|
public string Url { get; set; } = default!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace SpotifyAPI.Web
|
|||||||
/// A list of PlaylistTracks, which items can be a FullTrack or FullEpisode
|
/// A list of PlaylistTracks, which items can be a FullTrack or FullEpisode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value></value>
|
/// <value></value>
|
||||||
public Paging<PlaylistTrack<IPlayableItem>> Tracks { get; set; } = default!;
|
public Paging<PlaylistTrack<BasePlayableItem>> Tracks { get; set; } = default!;
|
||||||
public string Type { get; set; } = default!;
|
public string Type { get; set; } = default!;
|
||||||
public string Uri { get; set; } = default!;
|
public string Uri { get; set; } = default!;
|
||||||
}
|
}
|
||||||
|
13
SpotifyAPI.Web/Models/Response/TestResponseObject.cs
Normal file
13
SpotifyAPI.Web/Models/Response/TestResponseObject.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SpotifyAPI.Web
|
||||||
|
{
|
||||||
|
public class TestResponseObject
|
||||||
|
{
|
||||||
|
public bool HelloWorld { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -31,10 +31,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1">
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1">
|
||||||
<PrivateAssets>None</PrivateAssets>
|
<PrivateAssets>None</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="System.Text.Json" Version="6.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
Loading…
Reference in New Issue
Block a user