Files
plexcsharp/LukeHagar/PlexAPI/SDK/Utils/URLBuilder.cs
speakeasybot c0836c3b34 ## Csharp SDK Changes:
* `PlexApi.LibraryPlaylists.AddPlaylistItems()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LibraryPlaylists.ClearPlaylistItems()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LibraryCollections.MoveCollectionItem()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LibraryCollections.DeleteCollectionItem()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LibraryCollections.AddCollectionItems()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Content.GetSonicallySimilar()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Butler.StopTask()`:  `request` **Changed** **Breaking** ⚠️
* `PlexApi.Butler.StartTask()`:  `request` **Changed** **Breaking** ⚠️
* `PlexApi.Content.GetSonicPath()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.DownloadQueue.GetItemDecision()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Hubs.GetAllHubs()`: 
  *  `request.OnlyTransient` **Changed**
  *  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Hubs.GetContinueWatching()`:  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Hubs.GetPromotedHubs()`:  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Hubs.GetMetadataHubs()`: 
  *  `request.OnlyTransient` **Changed**
  *  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Hubs.GetPostplayHubs()`: 
  *  `request.OnlyTransient` **Changed**
  *  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Hubs.GetRelatedHubs()`: 
  *  `request.OnlyTransient` **Changed**
  *  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Hubs.GetSectionHubs()`: 
  *  `request.OnlyTransient` **Changed**
  *  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Content.GetAllLeaves()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Content.ListContent()`: 
  *  `request` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Search.SearchHubs()`:  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Content.GetAlbums()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetLibraryItems()`: 
  *  `request.MediaQuery` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.IngestTransientItem()`: 
  *  `request` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetLibraryMatches()`: 
  *  `request` **Changed** **Breaking** ⚠️
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Content.GetMetadataItem()`: 
  *  `request` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetSections()`:  `response.mediaContainer.Directory.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.AddSection()`: 
  *  `request` **Changed**
  *  `response.mediaContainer.Directory.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetTags()`: 
  *  `request.Type` **Changed** **Breaking** ⚠️
* `PlexApi.Content.GetCollectionItems()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetAllItemLeaves()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Status.ListSessions()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.PlayQueue.MovePlayQueueItem()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetExtras()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.PlayQueue.DeletePlayQueueItem()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.PlayQueue.Unshuffle()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.ListMatches()`: 
  *  `request.Manual` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.ListSonicallySimilar()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.PlayQueue.Shuffle()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetRelatedItems()`:  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.ListSimilar()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.PlayQueue.ResetPlayQueue()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetItemTree()`:  `response.mediaContainer.MetadataItem.[]` **Changed** **Breaking** ⚠️
* `PlexApi.PlayQueue.ClearPlayQueue()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.PlayQueue.AddToPlayQueue()`: 
  *  `request.Next` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetCommon()`: 
  *  `request.MediaQuery` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetPerson()`:  `response.mediaContainer.Directory.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.ListPersonMedia()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.PlayQueue.GetPlayQueue()`: 
  *  `request` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetLibraryDetails()`: 
  *  `request.IncludeDetails` **Changed**
  *  `response.mediaContainer.Directory.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LibraryPlaylists.MovePlaylistItem()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.Autocomplete()`: 
  *  `request.MediaQuery` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Library.GetCollections()`: 
  *  `request.MediaQuery` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LibraryPlaylists.GetPlaylistGeneratorItems()`:  `response.mediaContainer.Metadata` **Changed** **Breaking** ⚠️
* `PlexApi.LibraryPlaylists.DeletePlaylistItem()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Search.VoiceSearchHubs()`: 
  *  `request.Type` **Changed** **Breaking** ⚠️
  *  `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LibraryPlaylists.CreatePlaylist()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Playlist.GetPlaylistItems()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Playlist.GetPlaylist()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Playlist.ListPlaylists()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Collections.CreateCollection()`: 
  *  `request.Type` **Changed** **Breaking** ⚠️
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.DvRs.TuneChannel()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LiveTv.GetSessions()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.LiveTv.GetLiveTvSession()`:  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Transcoder.MakeDecision()`: 
  *  `request` **Changed**
  *  `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️
* `PlexApi.Subscriptions.GetAllSubscriptions()`: 
  *  `request` **Changed**
  *  `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️
* `PlexApi.Subscriptions.CreateSubscription()`:  `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️
* `PlexApi.Subscriptions.GetScheduledRecordings()`:  `response.mediaContainer.MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️
* `PlexApi.Subscriptions.GetTemplate()`:  `response.mediaContainer.SubscriptionTemplate.[].MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️
* `PlexApi.Subscriptions.GetSubscription()`: 
  *  `request` **Changed**
  *  `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️
* `PlexApi.Subscriptions.EditSubscriptionPreferences()`:  `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️
* `PlexApi.Subscriptions.ReorderSubscription()`:  `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️
* `PlexApi.Library.AddSubtitles()`:  `request` **Changed**
* `PlexApi.LibraryPlaylists.UploadPlaylist()`: 
  *  `request.Force` **Changed**
* `PlexApi.Transcoder.TranscodeSubtitles()`:  `request` **Changed**
* `PlexApi.Transcoder.StartTranscodeSession()`:  `request` **Changed**
* `PlexApi.Library.GetMediaPart()`: 
  *  `request.Download` **Changed**
* `PlexApi.Library.DetectIntros()`: 
  *  `request.Force` **Changed**
* `PlexApi.Library.GetSectionImage()`: 
  *  `request.MediaQuery` **Changed**
* `PlexApi.Library.DeleteMediaItem()`: 
  *  `request.Proxy` **Changed**
* `PlexApi.Library.RefreshItemsMetadata()`: 
  *  `request.MarkUpdated` **Changed**
* `PlexApi.Authentication.Post-Users-Sign-In-Data()`: **Added**
* `PlexApi.Authentication.GetTokenDetails()`: **Added**
* `PlexApi.Library.DetectCredits()`:  `request` **Changed**
* `PlexApi.Library.SetStreamSelection()`: 
  *  `request.AllParts` **Changed**
* `PlexApi.Library.UpdateItems()`: 
  *  `request.Field.locked` **Changed**
* `PlexApi.PlayQueue.CreatePlayQueue()`:  `request` **Changed**
* `PlexApi.Library.DeleteLibrarySection()`: 
  *  `request.Async` **Changed**
* `PlexApi.Library.GetAugmentationStatus()`: 
  *  `request.Wait` **Changed**
* `PlexApi.Transcoder.TranscodeImage()`:  `request` **Changed**
* `PlexApi.Devices.ModifyDevice()`: 
  *  `request.Enabled` **Changed**
* `PlexApi.Library.DetectVoiceActivity()`:  `request` **Changed**
* `PlexApi.Library.GetStream()`: 
  *  `request.AutoAdjustSubtitle` **Changed**
* `PlexApi.Library.StartBifGeneration()`: 
  *  `request.Force` **Changed**
* `PlexApi.Library.GetFirstCharacters()`: 
  *  `request.MediaQuery` **Changed**
* `PlexApi.UltraBlur.GetImage()`: 
  *  `request.Noise` **Changed**
* `PlexApi.Library.GenerateThumbs()`: 
  *  `request.Force` **Changed**
* `PlexApi.Updater.ApplyUpdates()`:  `request` **Changed**
* `PlexApi.Updater.CheckUpdates()`: 
  *  `request.Download` **Changed**
* `PlexApi.Library.DeleteMetadataItem()`: 
  *  `request.Proxy` **Changed**
* `PlexApi.Library.OptimizeDatabase()`: 
  *  `request.Async` **Changed**
* `PlexApi.Library.RefreshSection()`: 
  *  `request.Force` **Changed**
* `PlexApi.Hubs.UpdateHubVisibility()`:  `request` **Changed**
* `PlexApi.Hubs.CreateCustomHub()`:  `request` **Changed**
* `PlexApi.DownloadQueue.AddDownloadQueueItems()`:  `request` **Changed**
* `PlexApi.Timeline.Report()`:  `request` **Changed**
* `PlexApi.General.GetSourceConnectionInformation()`: 
  *  `request.Refresh` **Changed**
* `PlexApi.Plex.Get-Server-Resources()`: **Added**
* `PlexApi.Users.Get-Users()`: **Added**
2025-12-01 00:32:52 +00:00

636 lines
21 KiB
C#

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
//
// Changes to this file may cause incorrect behavior and will be lost when
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
#nullable enable
namespace LukeHagar.PlexAPI.SDK.Utils
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
internal static class URLBuilder
{
public static string Build(string baseUrl, string relativeUrl, object? request, List<string>? allowEmptyValue = null)
{
var url = baseUrl;
if (url.EndsWith("/"))
{
url = url.Substring(0, url.Length - 1);
}
var pathAndFragment = relativeUrl.Split('#');
if (pathAndFragment.Length > 2)
{
throw new ArgumentException($"Malformed URL: {relativeUrl}");
}
url += pathAndFragment[0];
var parameters = GetPathParameters(request);
url = ReplaceParameters(url, parameters);
var queryParams = SerializeQueryParams(TrySerializeQueryParams(request, allowEmptyValue));
if (queryParams != "")
{
url += $"?{queryParams}";
}
if (pathAndFragment.Length == 2)
{
url += $"#{pathAndFragment[1]}";
}
return url;
}
public static string ReplaceParameters(string url, Dictionary<string, string> parameters)
{
foreach (var key in parameters.Keys)
{
url = url.Replace($"{{{key}}}", Uri.EscapeDataString(parameters[key]));
}
return url;
}
public static string SerializeQueryParams(Dictionary<string, List<string>> queryParams) {
var queries = new List<string>();
foreach (var key in queryParams.Keys)
{
foreach (var value in queryParams[key])
{
queries.Add($"{key}={WebUtility.UrlEncode(Utilities.ToString(value))}");
}
}
return string.Join("&", queries);
}
private static Dictionary<string, string> GetPathParameters(object? request)
{
var parameters = new Dictionary<string, string>();
if (request == null)
{
return parameters;
}
var props = request.GetType().GetProperties();
foreach (var prop in props)
{
var val = prop.GetValue(request);
if (prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetRequestMetadata() != null)
{
continue;
}
var metadata = prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetPathParamMetadata();
if (metadata == null)
{
continue;
}
// Handle null values and empty arrays as empty query parameters
if (val == null || (Utilities.IsList(val) && ((IList)val).Count == 0))
{
parameters.Add(metadata.Name ?? prop.Name, "");
continue;
}
if (metadata.Serialization != null)
{
switch (metadata.Serialization)
{
case "json":
parameters.Add(
metadata.Name ?? prop.Name,
Utilities.SerializeJSON(val)
);
break;
default:
throw new Exception(
$"Unknown serialization type: {metadata.Serialization}"
);
}
}
else
{
switch (metadata.Style)
{
case "simple":
var simpleParams = SerializeSimplePathParams(
metadata.Name ?? prop.Name,
val,
metadata.Explode
);
foreach (var key in simpleParams.Keys)
{
parameters.Add(key, simpleParams[key]);
}
break;
default:
throw new Exception($"Unsupported path param style: {metadata.Style}");
}
}
}
return parameters;
}
private static Dictionary<string, List<string>> TrySerializeQueryParams(object? request, List<string>? allowEmptyValue = null)
{
var parameters = new Dictionary<string, List<string>>();
if (request == null)
{
return parameters;
}
var props = request.GetType().GetProperties();
foreach (var prop in props)
{
var val = prop.GetValue(request);
var metadata = prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetQueryParamMetadata();
if (val == null)
{
// If this parameter is in allowEmptyValue and val is null, include it as empty
if (metadata != null && allowEmptyValue?.Contains(metadata.Name ?? prop.Name) == true)
{
var paramName = metadata.Name ?? prop.Name;
if (!parameters.ContainsKey(paramName))
{
parameters.Add(paramName, new List<string>());
}
parameters[paramName].Add("");
}
continue;
}
if (prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetRequestMetadata() != null)
{
continue;
}
if (metadata == null)
{
continue;
}
if (metadata.Serialization != null)
{
switch (metadata.Serialization)
{
case "json":
if (!parameters.ContainsKey(metadata.Name ?? prop.Name))
{
parameters.Add(metadata.Name ?? prop.Name, new List<string>());
}
parameters[metadata.Name ?? prop.Name].Add(
Utilities.SerializeJSON(val)
);
break;
default:
throw new Exception(
$"Unknown serialization type: {metadata.Serialization}"
);
}
}
else
{
switch (metadata.Style)
{
case "form":
var formParams = SerializeFormQueryParams(
metadata.Name ?? prop.Name,
val,
metadata.Explode,
",",
allowEmptyValue
);
foreach (var key in formParams.Keys)
{
if (!parameters.ContainsKey(key))
{
parameters.Add(key, new List<string>());
}
foreach (var v in formParams[key])
{
parameters[key].Add(v);
}
}
break;
case "deepObject":
var deepObjParams = SerializeDeepObjectQueryParams(
metadata.Name ?? prop.Name,
val
);
foreach (var key in deepObjParams.Keys)
{
if (!parameters.ContainsKey(key))
{
parameters.Add(key, new List<string>());
}
foreach (var v in deepObjParams[key])
{
parameters[key].Add(v);
}
}
break;
case "pipeDelimited":
var pipeParams = SerializeFormQueryParams(
metadata.Name ?? prop.Name,
val,
metadata.Explode,
"|",
allowEmptyValue
);
foreach (var key in pipeParams.Keys)
{
if (!parameters.ContainsKey(key))
{
parameters.Add(key, new List<string>());
}
foreach (var v in pipeParams[key])
{
parameters[key].Add(v);
}
}
break;
default:
throw new Exception($"Unsupported query param style: {metadata.Style}");
}
}
}
return parameters;
}
private static Dictionary<string, string> SerializeSimplePathParams(
string parentName,
object value,
bool explode
)
{
var parameters = new Dictionary<string, string>();
if (Utilities.IsClass(value))
{
var vals = new List<string>();
var props = value.GetType().GetProperties();
foreach (var prop in props)
{
var val = prop.GetValue(value);
if (val == null)
{
continue;
}
var metadata = prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetPathParamMetadata();
if (metadata == null)
{
continue;
}
if (explode)
{
vals.Add($"{metadata.Name}={Utilities.ToString(val)}");
}
else
{
vals.Add($"{metadata.Name},{Utilities.ToString(val)}");
}
}
parameters.Add(parentName, string.Join(",", vals));
}
else if (Utilities.IsDictionary(value))
{
var vals = new List<string>();
foreach (var key in ((IDictionary)value).Keys)
{
if (key == null)
{
continue;
}
var val = ((IDictionary)value)[key];
if (explode)
{
vals.Add($"{key}={Utilities.ToString(val)}");
}
else
{
vals.Add($"{key},{Utilities.ToString(val)}");
}
}
parameters.Add(parentName, string.Join(",", vals));
}
else if (Utilities.IsList(value))
{
var vals = new List<string>();
foreach (var val in (IEnumerable)value)
{
vals.Add(Utilities.ToString(val));
}
parameters.Add(parentName, string.Join(",", vals));
}
else
{
parameters.Add(parentName, Utilities.ToString(value));
}
return parameters;
}
private static Dictionary<string, List<string>> SerializeFormQueryParams(
string parentName,
object value,
bool explode,
string delimiter,
List<string>? allowEmptyValue = null
)
{
var parameters = new Dictionary<string, List<string>>();
if (Utilities.IsClass(value) && !Utilities.IsDate(value))
{
var props = value.GetType().GetProperties();
var items = new List<string>();
foreach (var prop in props)
{
var val = prop.GetValue(value);
if (val == null)
{
continue;
}
var metadata = prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetQueryParamMetadata();
if (metadata == null || metadata.Name == null)
{
continue;
}
if (explode)
{
if (!parameters.ContainsKey(metadata.Name))
{
parameters.Add(metadata.Name, new List<string>());
}
parameters[metadata.Name].Add(
Utilities.ToString(val)
);
}
else
{
items.Add(
$"{metadata.Name}{delimiter}{Utilities.ValueToString(val)}"
);
}
}
if (items.Count > 0)
{
if (!parameters.ContainsKey(parentName))
{
parameters.Add(parentName, new List<string>());
}
parameters[parentName].Add(string.Join(delimiter, items));
}
}
else if (Utilities.IsDictionary(value))
{
var items = new List<string>();
foreach (var k in ((IDictionary)value).Keys)
{
var key = k?.ToString();
if (key == null)
{
continue;
}
if (explode)
{
if (!parameters.ContainsKey(key))
{
parameters.Add(key, new List<string>());
}
parameters[key].Add(
Utilities.ValueToString(((IDictionary)value)[key])
);
}
else
{
items.Add(
$"{key}{delimiter}{Utilities.ValueToString(((IDictionary)value)[key])}"
);
}
}
if (items.Count > 0)
{
if (!parameters.ContainsKey(parentName))
{
parameters.Add(parentName, new List<string>());
}
parameters[parentName].Add(string.Join(delimiter, items));
}
}
else if (Utilities.IsList(value))
{
var values = new List<string>();
var items = new List<string>();
var list = (IList)value;
// Handle empty arrays - add empty parameter if allowEmptyValue includes this parameter
if (list.Count == 0 && allowEmptyValue?.Contains(parentName) == true)
{
if (!parameters.ContainsKey(parentName))
{
parameters.Add(parentName, new List<string>());
}
parameters[parentName].Add("");
}
else
{
foreach (var item in list)
{
if (explode)
{
values.Add(Utilities.ValueToString(item));
}
else
{
items.Add(Utilities.ValueToString(item));
}
}
if (items.Count > 0)
{
values.Add(string.Join(delimiter, items));
}
foreach (var val in values)
{
if (!parameters.ContainsKey(parentName))
{
parameters.Add(parentName, new List<string>());
}
parameters[parentName].Add(val);
}
}
}
else
{
if (!parameters.ContainsKey(parentName))
{
parameters.Add(parentName, new List<string>());
}
// Handle null values and empty strings for allowEmptyValue parameters
var stringValue = Utilities.ValueToString(value);
if ((value == null || stringValue == "") && allowEmptyValue?.Contains(parentName) == true)
{
parameters[parentName].Add("");
}
else
{
parameters[parentName].Add(stringValue);
}
}
return parameters;
}
private static Dictionary<string, List<string>> SerializeDeepObjectQueryParams(
string parentName,
object value
)
{
var parameters = new Dictionary<string, List<string>>();
if (Utilities.IsClass(value))
{
var props = value.GetType().GetProperties();
foreach (var prop in props)
{
var val = prop.GetValue(value);
if (val == null)
{
continue;
}
var metadata = prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetQueryParamMetadata();
if (metadata == null || metadata.Name == null)
{
continue;
}
var keyName = $"{parentName}[{metadata.Name}]";
if (val != null && Utilities.IsList(val))
{
foreach (var v in (IList)val)
{
if (!parameters.ContainsKey(keyName))
{
parameters.Add(keyName, new List<string>());
}
parameters[keyName].Add(
Utilities.ValueToString(v)
);
}
}
else
{
if (!parameters.ContainsKey(keyName))
{
parameters.Add(keyName, new List<string>());
}
parameters[keyName].Add(Utilities.ValueToString(val));
}
}
}
else if (Utilities.IsDictionary(value))
{
foreach (var key in ((IDictionary)value).Keys)
{
if (key == null)
{
continue;
}
var val = ((IDictionary)value)[key];
var keyName = $"{parentName}[{key}]";
if (val != null && Utilities.IsList(val))
{
foreach (var v in (IList)val)
{
if (!parameters.ContainsKey(keyName))
{
parameters.Add(keyName, new List<string>());
}
parameters[keyName].Add(
Utilities.ValueToString(v)
);
}
}
else
{
if (!parameters.ContainsKey(keyName))
{
parameters.Add(keyName, new List<string>());
}
parameters[keyName].Add(Utilities.ValueToString(val));
}
}
}
return parameters;
}
}
}