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,39 @@
#if NET6_0_OR_GREATER
namespace Stripe.Infrastructure
{
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

/// <summary>
/// Converts a 64-bit integer to and from a string-encoded JSON integer.
/// </summary>
internal class STJStringInt64Converter : JsonConverter<long>
{
public override long Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
if (!long.TryParse(reader.GetString(), out long value))
{
throw new JsonException(string.Format("Cannot convert invalid value to {0}.", typeToConvert));
}

return value;
}

if (reader.TokenType == JsonTokenType.Number)
{
return reader.GetInt64();
}

throw new JsonException(string.Format("Unexpected token parsing integer. Expected String or Number, got {0}.", reader.TokenType));
}

public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
namespace Stripe.Infrastructure
{
using System;
using Newtonsoft.Json;

/// <summary>
/// Converts a 64-bit integer to and from a string-encoded JSON integer.
/// </summary>
public class StringInt64Converter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(long) || objectType == typeof(long?);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
return;
}

writer.WriteValue(value.ToString());
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
bool nullable = IsNullable(objectType);
if (reader.TokenType == JsonToken.Null)
{
if (!nullable)
{
throw new JsonSerializationException(string.Format("Cannot convert null value to {0}.", objectType));
}

return null;
}

long value;
if (reader.TokenType == JsonToken.String)
{
if (!long.TryParse((string)reader.Value!, out value))
{
throw new JsonSerializationException(string.Format("Cannot convert invalid value to {0}.", objectType));
}
}
else if (reader.TokenType == JsonToken.Integer)
{
value = (long)reader.Value!;
}
else
{
throw new JsonSerializationException(string.Format("Unexpected token parsing integer. Expected String or Integer, got {0}.", reader.TokenType));
}

return value;
}

private static bool IsNullable(Type t)
{
if (t == null)
{
throw new ArgumentNullException(nameof(t));
}

if (t.IsValueType)
{
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
}

return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace StripeTests
{
using Newtonsoft.Json;
using Stripe;
using Stripe.Infrastructure;
using Xunit;

public class StringInt64ConverterTest : BaseStripeTest
{
[Fact]
public void DeserializeString()
{
var json = "{\n \"divide_by\": \"123\"\n}";
var obj = JsonConvert.DeserializeObject<TestObject>(json);

Assert.Equal(123L, obj.DivideBy);
}

[Fact]
public void DeserializeInteger()
{
var json = "{\n \"divide_by\": 123\n}";
var obj = JsonConvert.DeserializeObject<TestObject>(json);

Assert.Equal(123L, obj.DivideBy);
}

[Fact]
public void SerializeLongAsString()
{
var obj = new TestObject
{
DivideBy = 123L,
};

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

private class TestObject : StripeEntity<TestObject>
{
[JsonProperty("divide_by")]
[JsonConverter(typeof(StringInt64Converter))]
internal long DivideBy { get; set; }
}
}
}
Loading