diff --git a/src/RobinTTY.NordigenApiClient.Tests/Serialization/TransactionTests.cs b/src/RobinTTY.NordigenApiClient.Tests/Serialization/TransactionTests.cs
index 291e11f..431eba6 100644
--- a/src/RobinTTY.NordigenApiClient.Tests/Serialization/TransactionTests.cs
+++ b/src/RobinTTY.NordigenApiClient.Tests/Serialization/TransactionTests.cs
@@ -10,20 +10,48 @@ namespace RobinTTY.NordigenApiClient.Tests.Serialization;
internal class TransactionTests
{
///
- /// Tests the correct deserialization of transactions.
+ /// Tests the correct deserialization of transactions with a single embedded currency exchange object.
///
[Test]
- public void DeserializeTransaction()
+ public void DeserializeTransactionWithSingleCurrencyExchange()
+ {
+ const string json =
+ "{ \"transactionId\": \"AB123456789\", \"entryReference\": \"123456789\", \"bookingDate\": \"2023-03-20\", \"bookingDateTime\": \"2023-03-20T00:00:00+00:00\", \"transactionAmount\": { \"amount\": \"-33.06\", \"currency\": \"GBP\" }, \"currencyExchange\": { \"sourceCurrency\": \"USD\", \"exchangeRate\": \"1.20961887\", \"unitCurrency\": \"USD\", \"targetCurrency\": \"GBP\", \"instructedAmount\": { \"amount\": \"-33.06\", \"currency\": \"GBP\" } }, \"remittanceInformationUnstructured\": \"my reference here\", \"additionalInformation\": \"123456789\", \"proprietaryBankTransactionCode\": \"OTHER_PURCHASE\", \"merchantCategoryCode\": \"5045\", \"internalTransactionId\": \"abcdef\" }";
+
+ var options = new JsonSerializerOptions
+ {
+ Converters = {new CultureSpecificDecimalConverter()}
+ };
+ var transaction = JsonSerializer.Deserialize(json, options);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(transaction!.CurrencyExchange, Is.Not.Null);
+ Assert.That(transaction.CurrencyExchange!.First().ExchangeRate, Is.EqualTo(1.20961887));
+ Assert.That(transaction.CurrencyExchange!.First().InstructedAmount!.Amount, Is.EqualTo(-33.06));
+ Assert.That(transaction.CurrencyExchange!.First().InstructedAmount!.Currency, Is.EqualTo("GBP"));
+ Assert.That(transaction.CurrencyExchange!.First().SourceCurrency, Is.EqualTo("USD"));
+ Assert.That(transaction.CurrencyExchange!.First().TargetCurrency, Is.EqualTo("GBP"));
+ Assert.That(transaction.CurrencyExchange!.First().UnitCurrency, Is.EqualTo("USD"));
+ Assert.That(transaction.CurrencyExchange!.First().QuotationDate, Is.Null);
+ });
+ }
+
+ ///
+ /// Tests the correct deserialization of transactions with multiple embedded currency exchange objects.
+ ///
+ [Test]
+ public void DeserializeTransactionWithMultipleCurrencyExchange()
{
const string json =
"{ \"transactionId\": \"AB123456789\", \"entryReference\": \"123456789\", \"bookingDate\": \"2023-03-20\", \"bookingDateTime\": \"2023-03-20T00:00:00+00:00\", \"transactionAmount\": { \"amount\": \"-33.06\", \"currency\": \"GBP\" }, \"currencyExchange\":[{\"sourceCurrency\":\"USD\",\"exchangeRate\":\"1.20961887\",\"unitCurrency\":\"USD\",\"targetCurrency\":\"GBP\"}], \"remittanceInformationUnstructured\": \"my reference here\", \"additionalInformation\": \"123456789\", \"proprietaryBankTransactionCode\": \"OTHER_PURCHASE\", \"merchantCategoryCode\": \"5045\", \"internalTransactionId\": \"abcdef\" }";
- // We need the culture specific decimal converter here, since it it accepting strings
var options = new JsonSerializerOptions
{
- Converters = {new JsonWebTokenConverter(), new GuidConverter(), new CultureSpecificDecimalConverter()}
+ Converters = { new CultureSpecificDecimalConverter() }
};
var transaction = JsonSerializer.Deserialize(json, options);
+
Assert.Multiple(() =>
{
Assert.That(transaction!.CurrencyExchange, Is.Not.Null);
diff --git a/src/RobinTTY.NordigenApiClient/JsonConverters/SingleOrArrayConverter.cs b/src/RobinTTY.NordigenApiClient/JsonConverters/SingleOrArrayConverter.cs
new file mode 100644
index 0000000..7feca25
--- /dev/null
+++ b/src/RobinTTY.NordigenApiClient/JsonConverters/SingleOrArrayConverter.cs
@@ -0,0 +1,42 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace RobinTTY.NordigenApiClient.JsonConverters;
+
+internal class SingleOrArrayConverter : JsonConverter
+ where TCollection : class, ICollection, new()
+{
+ public override TCollection? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ switch (reader.TokenType)
+ {
+ case JsonTokenType.Null:
+ return null;
+ case JsonTokenType.StartArray:
+ var list = new TCollection();
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonTokenType.EndArray) break;
+ var listItem = JsonSerializer.Deserialize(ref reader, options);
+ if (listItem != null) list.Add(listItem);
+ }
+ return list;
+ default:
+ var item = JsonSerializer.Deserialize(ref reader, options);
+ return item != null ? new TCollection {item} : null;
+ }
+ }
+
+ public override void Write(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options)
+ {
+ if (value.Count == 1)
+ JsonSerializer.Serialize(writer, value.First(), options);
+ else
+ {
+ writer.WriteStartArray();
+ foreach (var item in value)
+ JsonSerializer.Serialize(writer, item, options);
+ writer.WriteEndArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/RobinTTY.NordigenApiClient/Models/Responses/AmountCurrencyPair.cs b/src/RobinTTY.NordigenApiClient/Models/Responses/AmountCurrencyPair.cs
index cf30676..5458c5e 100644
--- a/src/RobinTTY.NordigenApiClient/Models/Responses/AmountCurrencyPair.cs
+++ b/src/RobinTTY.NordigenApiClient/Models/Responses/AmountCurrencyPair.cs
@@ -30,4 +30,4 @@ public AmountCurrencyPair(decimal amount, string currency)
Amount = amount;
Currency = currency;
}
-}
+}
\ No newline at end of file
diff --git a/src/RobinTTY.NordigenApiClient/Models/Responses/CurrencyExchange.cs b/src/RobinTTY.NordigenApiClient/Models/Responses/CurrencyExchange.cs
index 57e581a..a3aae10 100644
--- a/src/RobinTTY.NordigenApiClient/Models/Responses/CurrencyExchange.cs
+++ b/src/RobinTTY.NordigenApiClient/Models/Responses/CurrencyExchange.cs
@@ -7,6 +7,12 @@ namespace RobinTTY.NordigenApiClient.Models.Responses;
///
public class CurrencyExchange
{
+ ///
+ /// The instructed amount including details about the currency the amount is denominated in.
+ ///
+ [JsonPropertyName("instructedAmount")]
+ public AmountCurrencyPair? InstructedAmount { get; }
+
///
/// Currency from which an amount is to be converted in a currency conversion. ISO 4217 Alpha 3 currency code (e.g.
/// "USD").
@@ -51,6 +57,9 @@ public class CurrencyExchange
///
/// Creates a new instance of .
///
+ ///
+ /// The currency and amount as instructed by the debtor, if the actual settlement is of a different currency or amount
+ ///
///
/// Currency from which an amount is to be converted in a currency conversion. ISO 4217 Alpha
/// 3 currency code (e.g. "USD").
@@ -70,9 +79,10 @@ public class CurrencyExchange
///
/// Date at which an exchange rate is quoted.
/// Unique identification to unambiguously identify the foreign exchange contract.
- public CurrencyExchange(string sourceCurrency, string targetCurrency, string unitCurrency, decimal exchangeRate,
+ public CurrencyExchange(AmountCurrencyPair? instructedAmount, string sourceCurrency, string targetCurrency, string unitCurrency, decimal exchangeRate,
DateTime? quotationDate, string? contractIdentification)
{
+ InstructedAmount = instructedAmount;
SourceCurrency = sourceCurrency;
TargetCurrency = targetCurrency;
UnitCurrency = unitCurrency;
diff --git a/src/RobinTTY.NordigenApiClient/Models/Responses/Transaction.cs b/src/RobinTTY.NordigenApiClient/Models/Responses/Transaction.cs
index 907afbe..e614dee 100644
--- a/src/RobinTTY.NordigenApiClient/Models/Responses/Transaction.cs
+++ b/src/RobinTTY.NordigenApiClient/Models/Responses/Transaction.cs
@@ -1,4 +1,5 @@
-using System.Text.Json.Serialization;
+using RobinTTY.NordigenApiClient.JsonConverters;
+using System.Text.Json.Serialization;
namespace RobinTTY.NordigenApiClient.Models.Responses;
@@ -218,7 +219,8 @@ public class Transaction
/// Array of the report exchange rate.
///
[JsonPropertyName("currencyExchange")]
- public IEnumerable? CurrencyExchange { get; }
+ [JsonConverter(typeof(SingleOrArrayConverter, CurrencyExchange>))]
+ public List? CurrencyExchange { get; }
///
/// The identification of the transaction as used for reference by the financial institution.
@@ -343,7 +345,7 @@ public Transaction(string? transactionId, string? debtorName, MinimalBankAccount
DateTime? valueDateTime, string? remittanceInformationStructured,
IEnumerable? remittanceInformationStructuredArray, string? additionalInformation,
string? additionalInformationStructured, Balance? balanceAfterTransaction, string? checkId,
- IEnumerable? currencyExchange, string? entryReference, string? internalTransactionId,
+ List? currencyExchange, string? entryReference, string? internalTransactionId,
string? merchantCategoryCode, DateTime? bookingDateTime)
{
TransactionId = transactionId;