Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions src/Features/JsonPatch.SystemTextJson/src/Helpers/JsonUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Text.Json;
using System.Text.Json.Nodes;

Expand All @@ -10,8 +11,41 @@ internal static class JsonUtilities
{
public static bool DeepEquals(object a, object b, JsonSerializerOptions serializerOptions)
{
return JsonObject.DeepEquals(
JsonSerializer.SerializeToNode(a, serializerOptions),
JsonSerializer.SerializeToNode(b, serializerOptions));
if (a == null && b == null)
{
return true;
}

if (a == null || b == null)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for one of the inputs to be a JsonElement representing null while the other is just CLR null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, theoretically - maybe. I'd prefer to wait for actual feedback on this one from customers before trying to expand the implementation to cover that scenario too.

{
return false;
}

if (a.GetType() == typeof(JsonNode) && b.GetType() == typeof(JsonNode))
{
return JsonNode.DeepEquals((JsonNode)a, (JsonNode)b);
}

using var docA = TryGetJsonElement(a, serializerOptions, out var elementA);
using var docB = TryGetJsonElement(b, serializerOptions, out var elementB);

return JsonElement.DeepEquals(elementA, elementB);
}

private static IDisposable TryGetJsonElement(object item, JsonSerializerOptions serializerOptions, out JsonElement element)
{
IDisposable result = null;
if (item is JsonElement jsonElement)
{
element = jsonElement;
}
else
{
var docA = JsonSerializer.SerializeToDocument(item, serializerOptions);
element = docA.RootElement;
result = docA;
}

return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ internal static ConversionResult CopyTo(object value, Type typeToConvertTo, Json
// Workaround for the https://github.com/dotnet/runtime/issues/113926
if (targetType.Name == "JsonValuePrimitive`1")
{
targetType = typeof(JsonNode);
targetType = typeof(JsonElement);
}

try
Expand Down Expand Up @@ -84,6 +84,12 @@ private static bool IsNullableType(Type type)

private static object ConvertToTargetType(object value, Type targetType, JsonSerializerOptions serializerOptions)
{
return JsonSerializer.Deserialize(JsonSerializer.Serialize(value, serializerOptions), targetType, serializerOptions);
if (value is JsonElement jsonElement)
{
return JsonSerializer.Deserialize(jsonElement, targetType, serializerOptions);
}

using JsonDocument doc = JsonSerializer.SerializeToDocument(value, serializerOptions);
return JsonSerializer.Deserialize(doc.RootElement, targetType, serializerOptions);
}
}
13 changes: 0 additions & 13 deletions src/Features/JsonPatch.SystemTextJson/src/Internal/ListAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.JsonPatch.SystemTextJson.Helpers;
using Microsoft.Extensions.Internal;

Expand Down Expand Up @@ -257,10 +256,6 @@ protected virtual bool TryGetPositionInfo(int collectionCount, string segment, O
}
}

/// <summary>
/// This API supports infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected readonly struct PositionInfo
{
public PositionInfo(PositionType type, int index)
Expand All @@ -273,10 +268,6 @@ public PositionInfo(PositionType type, int index)
public int Index { get; }
}

/// <summary>
/// This API supports infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected enum PositionType
{
Index, // valid index
Expand All @@ -285,10 +276,6 @@ protected enum PositionType
OutOfBounds
}

/// <summary>
/// This API supports infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected enum OperationType
{
Add,
Expand Down
19 changes: 7 additions & 12 deletions src/Features/JsonPatch.SystemTextJson/src/JsonPatchDocumentOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -713,19 +713,14 @@ private List<string> GetPathSegments(Expression expr)

private string GetPropertyNameFromMemberExpression(MemberExpression memberExpression)
{
var jsonObjectContract = SerializerOptions.GetTypeInfo(memberExpression.Expression.Type);
if (jsonObjectContract != null)
var jsonTypeInfo = SerializerOptions.GetTypeInfo(memberExpression.Expression.Type);
if (jsonTypeInfo != null)
{
var jsonName = memberExpression.Member.Name;
var propNameAttribute = memberExpression.Member.GetCustomAttribute<JsonPropertyNameAttribute>();
if (propNameAttribute is not null)
{
jsonName = propNameAttribute.Name;
}

return jsonObjectContract.Properties
.First(jsonProperty => jsonProperty.Name == jsonName)
.Name;
var memberInfo = memberExpression.Member;
var matchingProp = jsonTypeInfo
.Properties
.First(jsonProp => jsonProp.AttributeProvider is MemberInfo mi && mi == memberInfo);
return matchingProp.Name;
}

return null;
Expand Down
Loading