Repository: dotnet/aspnetcore
File: src/Features/JsonPatch.SystemTextJson/src/JsonPatchDocumentOfT.cs (C#)

Code before:
                    from = op.from
                };

                allOps.Add(untypedOp);
            }
        }

        return allOps;
    }

    // Internal for testing
    internal string GetPath<TProp>(Expression<Func<TModel, TProp>> expr, string position)
    {
        var segments = GetPathSegments(expr.Body);
        var path = String.Join("/", segments);
        if (position != null)
        {
            path += "/" + position;
            if (segments.Count == 0)
            {
                return path;
            }
        }

        return "/" + path;
    }

    private List<string> GetPathSegments(Expression expr)
    {
        var listOfSegments = new List<string>();
        switch (expr.NodeType)
        {
            case ExpressionType.ArrayIndex:
                var binaryExpression = (BinaryExpression)expr;
                listOfSegments.AddRange(GetPathSegments(binaryExpression.Left));
                listOfSegments.Add(binaryExpression.Right.ToString());
                return listOfSegments;

            case ExpressionType.Call:
                var methodCallExpression = (MethodCallExpression)expr;
                listOfSegments.AddRange(GetPathSegments(methodCallExpression.Object));
                listOfSegments.Add(EvaluateExpression(methodCallExpression.Arguments[0]));
                return listOfSegments;

            case ExpressionType.Convert:
                listOfSegments.AddRange(GetPathSegments(((UnaryExpression)expr).Operand));
                return listOfSegments;

            case ExpressionType.MemberAccess:
                var memberExpression = expr as MemberExpression;
                listOfSegments.AddRange(GetPathSegments(memberExpression.Expression));

Review comment (performance):
[nitpick] Using string.Join with a char parameter is more efficient than using a string literal. Consider using string.Join("/", segments) for consistency with the rest of the codebase.

Code after:
                    value = op.value,
                    path = op.path,
                    from = op.from
                };

                allOps.Add(untypedOp);
            }
        }

        return allOps;
    }

    /// <inheritdoc/>
    static void IEndpointParameterMetadataProvider.PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
    {
        ArgumentNullException.ThrowIfNull(parameter);
        ArgumentNullException.ThrowIfNull(builder);

        builder.Metadata.Add(new AcceptsMetadata(["application/json-patch+json"], typeof(TModel)));
    }

    // Internal for testing
    internal string GetPath<TProp>(Expression<Func<TModel, TProp>> expr, string position)
    {
        var segments = GetPathSegments(expr.Body);
        var path = string.Join('/', segments);
        if (position != null)
        {
            path += "/" + position;
            if (segments.Count == 0)
            {
                return path;
            }
        }

        return "/" + path;
    }

    private List<string> GetPathSegments(Expression expr)
    {
        var listOfSegments = new List<string>();
        switch (expr.NodeType)
        {
            case ExpressionType.ArrayIndex:
                var binaryExpression = (BinaryExpression)expr;
                listOfSegments.AddRange(GetPathSegments(binaryExpression.Left));
                listOfSegments.Add(binaryExpression.Right.ToString());
                return listOfSegments;

            case ExpressionType.Call:
                var methodCallExpression = (MethodCallExpression)expr;