Skip to content

Commit

Permalink
OrderBy
Browse files Browse the repository at this point in the history
  • Loading branch information
StefH committed Apr 9, 2024
1 parent aa60751 commit d56b0d3
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq.Dynamic.Core.NewtonsoftJson.Config;
using System.Collections;
using System.Linq.Dynamic.Core.NewtonsoftJson.Config;
using System.Linq.Dynamic.Core.NewtonsoftJson.Extensions;
using System.Linq.Dynamic.Core.Validation;
using System.Linq.Expressions;
Expand Down Expand Up @@ -237,7 +238,7 @@ public static int Count(this JArray source, NewtonsoftJsonParsingConfig config,
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return queryable.Count(config, predicate, args);
}

Expand Down Expand Up @@ -343,7 +344,7 @@ public static JToken First(this JArray source, LambdaExpression lambda)
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJToken(queryable.FirstOrDefault(predicate, args));
}

Expand Down Expand Up @@ -388,7 +389,7 @@ public static JToken Last(this JArray source, NewtonsoftJsonParsingConfig config
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJToken(queryable.Last(predicate, args));
}

Expand Down Expand Up @@ -433,7 +434,7 @@ public static JToken Last(this JArray source, LambdaExpression lambda)
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJToken(queryable.LastOrDefault(predicate, args));
}

Expand Down Expand Up @@ -478,7 +479,7 @@ public static JToken Max(this JArray source, NewtonsoftJsonParsingConfig config,
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJToken(queryable.Max(config, predicate, args))!;
}

Expand Down Expand Up @@ -523,7 +524,7 @@ public static JToken Min(this JArray source, NewtonsoftJsonParsingConfig config,
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJToken(queryable.Min(config, predicate, args))!;
}

Expand Down Expand Up @@ -554,6 +555,66 @@ public static JToken Min(this JArray source, LambdaExpression lambda)
}
#endregion Min

#region OrderBy
/// <summary>
/// Sorts the elements of a sequence in ascending or descending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="config">The <see cref="NewtonsoftJsonParsingConfig"/>.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param>
/// <returns>A <see cref="JArray"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
public static JArray OrderBy(this JArray source, NewtonsoftJsonParsingConfig config, string ordering, params object?[] args)
{
Check.NotNull(source);
Check.NotNull(source);
Check.NotNullOrEmpty(ordering);

var queryable = ToQueryable(source, config);
return ToJArray(() => queryable.OrderBy(config, ordering, args));
}

/// <summary>
/// Sorts the elements of a sequence in ascending or descending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param>
/// <returns>A <see cref="JArray"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
public static JArray OrderBy(this JArray source, string ordering, params object?[] args)
{
return OrderBy(source, NewtonsoftJsonParsingConfig.Default, ordering, args);
}

/// <summary>
/// Sorts the elements of a sequence in ascending or descending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="config">The <see cref="NewtonsoftJsonParsingConfig"/>.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="comparer">The comparer to use.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param>
/// <returns>A <see cref="JArray"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
public static JArray OrderBy(this JArray source, NewtonsoftJsonParsingConfig config, string ordering, IComparer comparer, params object?[] args)
{
var queryable = ToQueryable(source, config);
return ToJArray(() => queryable.OrderBy(config, ordering, comparer, args));
}

/// <summary>
/// Sorts the elements of a sequence in ascending or descending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="comparer">The comparer to use.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param>
/// <returns>A <see cref="JArray"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
public static JArray OrderBy(this JArray source, string ordering, IComparer comparer, params object?[] args)
{
return OrderBy(source, NewtonsoftJsonParsingConfig.Default, ordering, comparer, args);
}
#endregion OrderBy

#region Select
/// <summary>
/// Projects each element of a sequence into a new form.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ public class SystemTextJsonParsingConfig : ParsingConfig
{
public static SystemTextJsonParsingConfig Default { get; } = new();

public DynamicJsonClassOptions? DynamicJsonClassOptions { get; set; }
// public DynamicJsonClassOptions? DynamicJsonClassOptions { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Dynamic.Core.SystemTextJson.Config;
using System.Linq.Dynamic.Core.SystemTextJson.Extensions;
using System.Linq.Dynamic.Core.SystemTextJson.Utils;
Expand Down Expand Up @@ -149,7 +150,7 @@ public static double Average(this JsonDocument source, SystemTextJsonParsingConf
Check.NotNull(config);
Check.NotEmpty(predicate);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return queryable.Average(config, predicate, args);
}

Expand Down Expand Up @@ -251,7 +252,7 @@ public static int Count(this JsonDocument source, SystemTextJsonParsingConfig co
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return queryable.Count(config, predicate, args);
}

Expand Down Expand Up @@ -411,7 +412,7 @@ public static JsonElement First(this JsonDocument source, LambdaExpression lambd
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJsonElement(queryable.FirstOrDefault(predicate, args));
}

Expand Down Expand Up @@ -469,7 +470,7 @@ public static JsonElement Last(this JsonDocument source, SystemTextJsonParsingCo
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJsonElement(queryable.Last(predicate, args));
}

Expand Down Expand Up @@ -527,7 +528,7 @@ public static JsonElement Last(this JsonDocument source, LambdaExpression lambda
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJsonElement(queryable.LastOrDefault(config, predicate, args));
}

Expand Down Expand Up @@ -585,7 +586,7 @@ public static JsonElement Max(this JsonDocument source, SystemTextJsonParsingCon
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJsonElement(queryable.Max(config, predicate, args)) ?? default;
}

Expand Down Expand Up @@ -643,7 +644,7 @@ public static JsonElement Min(this JsonDocument source, SystemTextJsonParsingCon
Check.NotNull(source);
Check.NotNull(config);

var queryable = ToQueryable(source);
var queryable = ToQueryable(source, config);
return ToJsonElement(queryable.Min(config, predicate, args)) ?? default;
}

Expand Down Expand Up @@ -674,6 +675,66 @@ public static JsonElement Min(this JsonDocument source, LambdaExpression lambda)
}
#endregion Min

#region OrderBy
/// <summary>
/// Sorts the elements of a sequence in ascending or descending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="config">The <see cref="SystemTextJsonParsingConfig"/>.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param>
/// <returns>A <see cref="JsonDocument"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
public static JsonDocument OrderBy(this JsonDocument source, SystemTextJsonParsingConfig config, string ordering, params object?[] args)
{
Check.NotNull(source);
Check.NotNull(source);
Check.NotNullOrEmpty(ordering);

var queryable = ToQueryable(source, config);
return ToJsonDocumentArray(() => queryable.OrderBy(config, ordering, args));
}

/// <summary>
/// Sorts the elements of a sequence in ascending or descending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param>
/// <returns>A <see cref="JsonDocument"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
public static JsonDocument OrderBy(this JsonDocument source, string ordering, params object?[] args)
{
return OrderBy(source, SystemTextJsonParsingConfig.Default, ordering, args);
}

/// <summary>
/// Sorts the elements of a sequence in ascending or descending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="config">The <see cref="SystemTextJsonParsingConfig"/>.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="comparer">The comparer to use.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param>
/// <returns>A <see cref="JsonDocument"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
public static JsonDocument OrderBy(this JsonDocument source, SystemTextJsonParsingConfig config, string ordering, IComparer comparer, params object?[] args)
{
var queryable = ToQueryable(source, config);
return ToJsonDocumentArray(() => queryable.OrderBy(config, ordering, comparer, args));
}

/// <summary>
/// Sorts the elements of a sequence in ascending or descending order according to a key.
/// </summary>
/// <param name="source">A sequence of values to order.</param>
/// <param name="ordering">An expression string to indicate values to order by.</param>
/// <param name="comparer">The comparer to use.</param>
/// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param>
/// <returns>A <see cref="JsonDocument"/> whose elements are sorted according to the specified <paramref name="ordering"/>.</returns>
public static JsonDocument OrderBy(this JsonDocument source, string ordering, IComparer comparer, params object?[] args)
{
return OrderBy(source, SystemTextJsonParsingConfig.Default, ordering, comparer, args);
}
#endregion OrderBy

#region Select
/// <summary>
/// Projects each element of a sequence into a new form.
Expand Down Expand Up @@ -765,6 +826,7 @@ private static JsonDocument ToJsonDocumentArray(Func<IQueryable> func)
return JsonDocumentUtils.FromObject(array);
}

// ReSharper disable once UnusedParameter.Local
private static IQueryable ToQueryable(JsonDocument source, SystemTextJsonParsingConfig? config = null)
{
var array = source.RootElement;
Expand All @@ -773,7 +835,7 @@ private static IQueryable ToQueryable(JsonDocument source, SystemTextJsonParsing
throw new NotSupportedException("The source is not a JSON array.");
}

return JsonDocumentExtensions.ToDynamicJsonClassArray(array, config?.DynamicJsonClassOptions).AsQueryable();
return JsonDocumentExtensions.ToDynamicJsonClassArray(array).AsQueryable();
}
#endregion
}
31 changes: 15 additions & 16 deletions src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1565,11 +1565,23 @@ public static IOrderedQueryable OrderBy(this IQueryable source, ParsingConfig co
return InternalOrderBy(source, config, ordering, comparer, args);
}

/// <inheritdoc cref="OrderBy(IQueryable, ParsingConfig, string, object[])"/>
public static IOrderedQueryable OrderBy(this IQueryable source, string ordering, params object?[] args)
{
return OrderBy(source, ParsingConfig.Default, ordering, args);
}

/// <inheritdoc cref="OrderBy(IQueryable, ParsingConfig, string, IComparer, object[])"/>
public static IOrderedQueryable OrderBy(this IQueryable source, string ordering, IComparer comparer, params object?[] args)
{
return OrderBy(source, ParsingConfig.Default, ordering, comparer, args);
}

internal static IOrderedQueryable InternalOrderBy(IQueryable source, ParsingConfig config, string ordering, object? comparer, params object?[] args)
{
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(ordering, nameof(ordering));
Check.NotEmpty(ordering);

ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(source.ElementType, string.Empty, config.RenameEmptyParameterExpressionNames) };
ExpressionParser parser = new ExpressionParser(parameters, ordering, args, config);
Expand Down Expand Up @@ -1616,19 +1628,6 @@ internal static IOrderedQueryable InternalOrderBy(IQueryable source, ParsingConf
var optimized = OptimizeExpression(queryExpr);
return (IOrderedQueryable)source.Provider.CreateQuery(optimized);
}

/// <inheritdoc cref="OrderBy(IQueryable, ParsingConfig, string, object[])"/>
public static IOrderedQueryable OrderBy(this IQueryable source, string ordering, params object?[] args)
{
return OrderBy(source, ParsingConfig.Default, ordering, args);
}

/// <inheritdoc cref="OrderBy(IQueryable, ParsingConfig, string, IComparer, object[])"/>
public static IOrderedQueryable OrderBy(this IQueryable source, string ordering, IComparer comparer, params object?[] args)
{
return OrderBy(source, ParsingConfig.Default, ordering, comparer, args);
}

#endregion OrderBy

#region Page/PageResult
Expand Down Expand Up @@ -1803,10 +1802,10 @@ public static IQueryable<TResult> Select<TResult>(this IQueryable source, Parsin
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, typeof(TResult), selector, args);

var methodCallExpression = Expression.Call(
typeof(Queryable),
typeof(Queryable),
nameof(Queryable.Select),
new[] { source.ElementType, typeof(TResult) },
source.Expression,
source.Expression,
Expression.Quote(lambda)
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,24 @@ public void Min()
((string?)_source.Min("Age")).Should().Be("30");
}

[Fact]
public void OrderBy()
{
// Act 1
var result = _source.OrderBy("Age").Select("Name");

// Assert 1
var array = result.Select(x => x.Value<string>());
array.Should().BeEquivalentTo("John", "Doe");

// Act 1
var resultAsc = _source.OrderBy("Age", "Asc").Select("Name");

// Assert 1
var arrayAsc = resultAsc.Select(x => x.Value<string>());
arrayAsc.Should().BeEquivalentTo("Doe", "John");
}

[Fact]
public void Select()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,24 @@ public void Min()
_source.Min("Age").GetRawText().Should().BeEquivalentTo("30");
}

[Fact]
public void OrderBy()
{
// Act 1
var result = _source.OrderBy("Age").Select("Name");

// Assert 1
var array = result.RootElement.EnumerateArray().Select(x => x.GetString());
array.Should().BeEquivalentTo("John", "Doe");

// Act 1
var resultAsc = _source.OrderBy("Age", "Asc").Select("Name");

// Assert 1
var arrayAsc = resultAsc.RootElement.EnumerateArray().Select(x => x.GetString());
arrayAsc.Should().BeEquivalentTo("Doe", "John");
}

[Fact]
public void Select()
{
Expand Down

0 comments on commit d56b0d3

Please sign in to comment.