File: IntegrationTests\HeterogenousCollectionTests.cs
Web Access
Project: src\src\Features\JsonPatch\test\Microsoft.AspNetCore.JsonPatch.Tests.csproj (Microsoft.AspNetCore.JsonPatch.Tests)
// 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.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using Xunit;
 
namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests;
 
public class HeterogenousCollectionTests
{
    [Fact]
    public void AddItemToList()
    {
        // Arrange
        var targetObject = new Canvas()
        {
            Items = new List<Shape>()
        };
 
        var circleJObject = JObject.Parse(@"{
              Type: 'Circle',
              ShapeProperty: 'Shape property',
              CircleProperty: 'Circle property'
            }"{
              Type: 'Circle',
              ShapeProperty: 'Shape property',
              CircleProperty: 'Circle property'
            }");
 
        var patchDocument = new JsonPatchDocument
        {
            ContractResolver = new CanvasContractResolver()
        };
 
        patchDocument.Add("/Items/-", circleJObject);
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        var circle = targetObject.Items[0] as Circle;
        Assert.NotNull(circle);
        Assert.Equal("Shape property", circle.ShapeProperty);
        Assert.Equal("Circle property", circle.CircleProperty);
    }
}
 
public class CanvasContractResolver : DefaultContractResolver
{
    protected override JsonConverter ResolveContractConverter(Type objectType)
    {
        if (objectType == typeof(Shape))
        {
            return new ShapeJsonConverter();
        }
 
        return base.ResolveContractConverter(objectType);
    }
}
 
public class ShapeJsonConverter : CustomCreationConverter<Shape>
{
    private const string TypeProperty = "Type";
 
    public override bool CanRead => true;
 
    public override Shape Create(Type objectType)
    {
        throw new NotImplementedException();
    }
 
    public override object ReadJson(
        JsonReader reader,
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
 
        var target = CreateShape(jObject);
        serializer.Populate(jObject.CreateReader(), target);
 
        return target;
    }
 
    private Shape CreateShape(JObject jObject)
    {
        var typeProperty = jObject.GetValue(TypeProperty).ToString();
 
        switch (typeProperty)
        {
            case "Circle":
                return new Circle();
 
            case "Rectangle":
                return new Rectangle();
        }
 
        throw new NotSupportedException();
    }
}