Merge pull request #1783 from Kukks/numeric-json-converter

Make Decimal json converter work for other number types
This commit is contained in:
Nicolas Dorier 2020-07-29 16:44:51 +09:00 committed by GitHub
commit 2d3b0717f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 78 additions and 52 deletions

View File

@ -1,39 +0,0 @@
using System;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.JsonConverters
{
public class DecimalStringJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(decimal) || objectType == typeof(decimal?));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
switch (token.Type)
{
case JTokenType.Float:
case JTokenType.Integer:
case JTokenType.String:
return decimal.Parse(token.ToString(), CultureInfo.InvariantCulture);
case JTokenType.Null when objectType == typeof(decimal?):
return null;
default:
throw new JsonSerializationException("Unexpected token type: " +
token.Type);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(((decimal)value).ToString(CultureInfo.InvariantCulture));
}
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.JsonConverters
{
public class NumericStringJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(decimal) ||
objectType == typeof(decimal?) ||
objectType == typeof(double) ||
objectType == typeof(double?));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
switch (token.Type)
{
case JTokenType.Float:
case JTokenType.Integer:
case JTokenType.String:
if (objectType == typeof(decimal) || objectType == typeof(decimal?) )
return decimal.Parse(token.ToString(), CultureInfo.InvariantCulture);
if (objectType == typeof(double) || objectType == typeof(double?))
return double.Parse(token.ToString(), CultureInfo.InvariantCulture);
throw new JsonSerializationException("Unexpected object type: " + objectType);
case JTokenType.Null when objectType == typeof(decimal?) || objectType == typeof(double?):
return null;
default:
throw new JsonSerializationException("Unexpected token type: " +
token.Type);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
switch (value)
{
case null:
break;
case decimal x:
writer.WriteValue(x.ToString(CultureInfo.InvariantCulture));
break;
case double x:
writer.WriteValue(x.ToString(CultureInfo.InvariantCulture));
break;
}
}
}
}

View File

@ -6,7 +6,7 @@ namespace BTCPayServer.Client.Models
public class CreatePayoutRequest
{
public string Destination { get; set; }
[JsonConverter(typeof(DecimalStringJsonConverter))]
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? Amount { get; set; }
public string PaymentMethod { get; set; }
}

View File

@ -8,7 +8,7 @@ namespace BTCPayServer.Client.Models
public class CreatePullPaymentRequest
{
public string Name { get; set; }
[JsonProperty(ItemConverterType = typeof(DecimalStringJsonConverter))]
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public string Currency { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter))]

View File

@ -8,7 +8,7 @@ namespace BTCPayServer.Client.Models
{
public class PaymentRequestBaseData
{
[JsonProperty(ItemConverterType = typeof(DecimalStringJsonConverter))]
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public string Currency { get; set; }
public DateTime? ExpiryDate { get; set; }

View File

@ -21,9 +21,9 @@ namespace BTCPayServer.Client.Models
public string PullPaymentId { get; set; }
public string Destination { get; set; }
public string PaymentMethod { get; set; }
[JsonConverter(typeof(DecimalStringJsonConverter))]
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
[JsonConverter(typeof(DecimalStringJsonConverter))]
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? PaymentMethodAmount { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public PayoutState State { get; set; }

View File

@ -14,7 +14,7 @@ namespace BTCPayServer.Client.Models
public string Id { get; set; }
public string Name { get; set; }
public string Currency { get; set; }
[JsonConverter(typeof(DecimalStringJsonConverter))]
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter))]
public TimeSpan? Period { get; set; }

View File

@ -734,17 +734,18 @@ namespace BTCPayServer.Tests
[Fact(Timeout = TestTimeout)]
[Trait("Fast", "Fast")]
public void DecimalStringJsonConverterTests()
public void NumericJsonConverterTests()
{
JsonReader Get(string val)
{
return new JsonTextReader(new StringReader(val));
}
var jsonConverter = new DecimalStringJsonConverter();
var jsonConverter = new NumericStringJsonConverter();
Assert.True(jsonConverter.CanConvert(typeof(decimal)));
Assert.True(jsonConverter.CanConvert(typeof(decimal?)));
Assert.False(jsonConverter.CanConvert(typeof(double)));
Assert.True(jsonConverter.CanConvert(typeof(double)));
Assert.True(jsonConverter.CanConvert(typeof(double?)));
Assert.False(jsonConverter.CanConvert(typeof(float)));
Assert.False(jsonConverter.CanConvert(typeof(int)));
Assert.False(jsonConverter.CanConvert(typeof(string)));
@ -755,12 +756,20 @@ namespace BTCPayServer.Tests
Assert.Equal(1m, jsonConverter.ReadJson(Get(numberJson), typeof(decimal), null, null));
Assert.Equal(1.2m, jsonConverter.ReadJson(Get(numberDecimalJson), typeof(decimal), null, null));
Assert.Null(jsonConverter.ReadJson(Get("null"), typeof(decimal?), null, null));
Assert.Equal((double)1.0, jsonConverter.ReadJson(Get(numberJson), typeof(double), null, null));
Assert.Equal((double)1.2, jsonConverter.ReadJson(Get(numberDecimalJson), typeof(double), null, null));
Assert.Null(jsonConverter.ReadJson(Get("null"), typeof(double?), null, null));
Assert.Throws<JsonSerializationException>(() =>
{
jsonConverter.ReadJson(Get("null"), typeof(decimal), null, null);
});Assert.Throws<JsonSerializationException>(() =>
{
jsonConverter.ReadJson(Get("null"), typeof(double), null, null);
});
Assert.Equal(1.2m, jsonConverter.ReadJson(Get(stringJson), typeof(decimal), null, null));
Assert.Equal(1.2m, jsonConverter.ReadJson(Get(stringJson), typeof(decimal?), null, null));
Assert.Equal(1.2, jsonConverter.ReadJson(Get(stringJson), typeof(double), null, null));
Assert.Equal(1.2, jsonConverter.ReadJson(Get(stringJson), typeof(double?), null, null));
}
}
}

View File

@ -149,9 +149,9 @@ namespace BTCPayServer.Data
}
public class PayoutBlob
{
[JsonConverter(typeof(DecimalStringJsonConverter))]
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
[JsonConverter(typeof(DecimalStringJsonConverter))]
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? CryptoAmount { get; set; }
public int MinimumConfirmation { get; set; } = 1;
public IClaimDestination Destination { get; set; }
@ -190,9 +190,9 @@ namespace BTCPayServer.Data
public string Name { get; set; }
public string Currency { get; set; }
public int Divisibility { get; set; }
[JsonConverter(typeof(DecimalStringJsonConverter))]
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Limit { get; set; }
[JsonConverter(typeof(DecimalStringJsonConverter))]
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal MinimumClaim { get; set; }
public PullPaymentView View { get; set; } = new PullPaymentView();
[JsonConverter(typeof(TimeSpanJsonConverter))]