Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
namespace StripeTests
{
using System.Text.Json;
using System.Text.Json.Serialization;
using Stripe;
using Stripe.Infrastructure;
using Xunit;

public class STJAnyOfConverterTest : BaseStripeTest
{
[Fact]
public void DeserializeFirstType()
{
var json = "{\n \"any_of\": \"String!\"\n}";
var obj = JsonSerializer.Deserialize<TestObject>(json);

Assert.NotNull(obj.AnyOf);
Assert.Equal("String!", obj.AnyOf);
}

[Fact]
public void DeserializeSecondType()
{
var json = "{\n \"any_of\": {\n \"id\": \"id_123\",\n \"bar\": 42\n }\n}";
var obj = JsonSerializer.Deserialize<TestObject>(json);

Assert.NotNull(obj.AnyOf);
Assert.Equal("id_123", ((TestSubObject)obj.AnyOf).Id);
Assert.Equal(42, ((TestSubObject)obj.AnyOf).Bar);
}

[Fact]
public void DeserializeNull()
{
var json = "{\n \"any_of\": null\n}";
var obj = JsonSerializer.Deserialize<TestObject>(json);

Assert.Null(obj.AnyOf);
}

[Fact]
public void DeserializeUnexpectedType()
{
var json = "{\n \"any_of\": []\n}";

var exception = Assert.Throws<JsonException>(() =>
JsonSerializer.Deserialize<TestObject>(json));

Assert.Contains(
"Cannot deserialize the current JSON object into any of the expected types",
exception.Message);
}

[Fact]
public void SerializeFirstType()
{
var obj = new TestObject
{
AnyOf = "String!",
};

var expected = "{\n \"any_of\": \"String!\"\n}";
Assert.Equal(expected, obj.ToJson().Replace("\r\n", "\n"));
}

[Fact]
public void SerializeSecondType()
{
var obj = new TestObject
{
AnyOf = new TestSubObject
{
Id = "id_123",
Bar = 42,
},
};

var expected =
"{\n \"any_of\": {\n \"id\": \"id_123\",\n \"bar\": 42\n }\n}";
Assert.Equal(expected, obj.ToJson().Replace("\r\n", "\n"));
}

[Fact]
public void SerializeNull()
{
var obj = new TestObject
{
AnyOf = null,
};

var expected = "{\n \"any_of\": null\n}";
Assert.Equal(expected, obj.ToJson().Replace("\r\n", "\n"));
}

[JsonConverter(typeof(STJStripeEntityConverter))]
private class TestSubObject : StripeEntity<TestSubObject>, IHasId
{
[JsonPropertyName("id")]
public string Id { get; set; }

[JsonPropertyName("bar")]
public int Bar { get; set; }
}

[JsonConverter(typeof(STJStripeEntityConverter))]
private class TestObject : StripeEntity<TestObject>
{
[JsonPropertyName("any_of")]
[JsonConverter(typeof(STJAnyOfConverter))]
internal AnyOf<string, TestSubObject> AnyOf { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
namespace StripeTests
{
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Stripe;
using Stripe.Infrastructure;
using Xunit;

public class STJExpandableFieldConverterTest : BaseStripeTest
{
[Fact]
public void DeserializeNotExpanded()
{
var json = "{\n \"nested\": \"id_not_expanded\"\n}";
var obj = JsonSerializer.Deserialize<TestTopLevelObject>(json);

Assert.Equal("id_not_expanded", obj.NestedId);
Assert.Null(obj.Nested);
}

[Fact]
public void DeserializeExpanded()
{
var json = "{\n \"nested\": {\n \"id\": \"id_expanded\",\n \"bar\": 42\n }\n}";
var obj = JsonSerializer.Deserialize<TestTopLevelObject>(json);

Assert.Equal("id_expanded", obj.NestedId);
Assert.NotNull(obj.Nested);
Assert.Equal("id_expanded", obj.Nested.Id);
Assert.Equal(42, obj.Nested.Bar);
}

[Fact]
public void DeserializeNull()
{
var json = "{\n \"nested\": null\n}";
var obj = JsonSerializer.Deserialize<TestTopLevelObject>(json);

Assert.Null(obj.NestedId);
Assert.Null(obj.Nested);
}

[Fact]
public void SerializeNotExpanded()
{
var obj = new TestTopLevelObject
{
InternalNested = new ExpandableField<TestNestedObject>
{
Id = "id_not_expanded",
ExpandedObject = null,
},
};

var expected = "{\"nested\":\"id_not_expanded\"}";
var actual = JsonSerializer.Serialize(obj);
Assert.Equal(expected, actual);

var indentedExpected = "{\n \"nested\": \"id_not_expanded\"\n}";
var options = new JsonSerializerOptions { WriteIndented = true };
var indentedActual = JsonSerializer.Serialize(obj, options);
Assert.Equal(indentedExpected, indentedActual);
}

[Fact]
public void SerializeExpanded()
{
var nested = new TestNestedObject
{
Id = "id_expanded",
Bar = 42,
};
var obj = new TestTopLevelObject
{
InternalNested = new ExpandableField<TestNestedObject>
{
Id = nested.Id,
ExpandedObject = nested,
},
};

var expected =
"{\"nested\":{\"id\":\"id_expanded\",\"bar\":42}}";
var actual = JsonSerializer.Serialize(obj);
Assert.Equal(expected, actual);

var indentedExpected =
"{\n \"nested\": {\n \"id\": \"id_expanded\",\n \"bar\": 42\n }\n}";
var options = new JsonSerializerOptions { WriteIndented = true };
var indentedActual = JsonSerializer.Serialize(obj, options);
Assert.Equal(indentedExpected, indentedActual);
}

[Fact]
public void SerializeListOfExpanded()
{
var nested = new TestNestedObject
{
Id = "id_expanded",
Bar = 42,
};
var obj = new TestTopLevelObjectWithList
{
InternalNestedList = new List<ExpandableField<TestNestedObject>>()
{
new ExpandableField<TestNestedObject>
{
Id = nested.Id,
ExpandedObject = nested,
},
},
};

var expected =
"{\"nested_list\":[{\"id\":\"id_expanded\",\"bar\":42}]}";
var actual = JsonSerializer.Serialize(obj);
Assert.Equal(expected, actual);

var indentedExpected =
"{\n \"nested_list\": [\n {\n \"id\": \"id_expanded\",\n \"bar\": 42\n }\n ]\n}";
var options = new JsonSerializerOptions { WriteIndented = true };
var indentedActual = JsonSerializer.Serialize(obj, options);
Assert.Equal(indentedExpected, indentedActual);
}

[Fact]
public void SerializeNull()
{
var obj = new TestTopLevelObject
{
InternalNested = new ExpandableField<TestNestedObject>
{
Id = null,
ExpandedObject = null,
},
};

var expected = "{\"nested\":null}";
var actual = JsonSerializer.Serialize(obj);
Assert.Equal(expected, actual);

var indentedExpected = "{\n \"nested\": null\n}";
var options = new JsonSerializerOptions { WriteIndented = true };
var indentedActual = JsonSerializer.Serialize(obj, options);
Assert.Equal(indentedExpected, indentedActual);
}

private class TestNestedObject : StripeEntity<TestNestedObject>, IHasId
{
[JsonPropertyName("id")]
public string Id { get; set; }

[JsonPropertyName("bar")]
public int Bar { get; set; }
}

[JsonConverter(typeof(STJStripeEntityConverter))]
private class TestTopLevelObject : StripeEntity<TestTopLevelObject>
{
[JsonIgnore]
public string NestedId => this.InternalNested.Id;

[JsonIgnore]
public TestNestedObject Nested => this.InternalNested.ExpandedObject;

[JsonPropertyName("nested")]
[JsonConverter(typeof(STJExpandableFieldConverter<TestNestedObject>))]
internal ExpandableField<TestNestedObject> InternalNested { get; set; }
}

[JsonConverter(typeof(STJStripeEntityConverter))]
private class TestTopLevelObjectWithList : StripeEntity<TestTopLevelObjectWithList>
{
[JsonIgnore]
public List<string> NestedListIds
{
get => this.InternalNestedList?.Select((x) => x.Id).ToList();
set => this.InternalNestedList = SetExpandableArrayIds<TestNestedObject>(value);
}

[JsonIgnore]
public List<TestNestedObject> NestedList
{
get => this.InternalNestedList?.Select((x) => x.ExpandedObject).ToList();
set => this.InternalNestedList = SetExpandableArrayObjects(value);
}

[JsonPropertyName("nested_list")]
internal List<ExpandableField<TestNestedObject>> InternalNestedList { get; set; }
}
}
}
7 changes: 7 additions & 0 deletions src/StripeTests/Wholesome/CorrectJsonConvertersForTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ public void Check()
continue;
}

// if we have a Int64StringConverter on a long type, assume its good.
if ((property.PropertyType == typeof(long) || property.PropertyType == typeof(long?))
&& actualConverterName == "Int64StringConverter")
{
continue;
}

results.Add(
$"{stripeClass.Name}.{property.Name}, expected = {expectedConverterName}, "
+ $"actual = {actualConverterName}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,24 @@ public void Check()
}
}

if (property.PropertyType == typeof(long) || property.PropertyType == typeof(long?))
{
var jsonAttribute = property.GetCustomAttribute(typeof(Newtonsoft.Json.JsonConverterAttribute), false) as Newtonsoft.Json.JsonConverterAttribute;
var stjAttribute = property.GetCustomAttribute(typeof(JsonNumberHandlingAttribute)) as JsonNumberHandlingAttribute;
if (jsonAttribute?.ConverterType == typeof(Int64StringConverter))
{
var hasCorrectAttributes =
(stjAttribute.Handling & (JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)) != 0;

if (!hasCorrectAttributes)
{
results.Add($"{type.FullName}.{property.Name}");
}

continue;
}
}

foreach (Attribute attribute in property.GetCustomAttributes())
{
if (attribute.GetType().Namespace.StartsWith("Newtonsoft", true, null))
Expand Down
Loading