Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.Text.Json Serialization Support in .NET SDK Objects #3033

Merged
merged 37 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9b040c7
moved Wholesome tests to their own namespace, for test output clarity
jar-stripe Nov 15, 2024
64908c5
added STJ attributes to base classes
jar-stripe Nov 15, 2024
aa40386
added STJ attributes to generated types
jar-stripe Nov 15, 2024
34a0381
added/updated wholesome tests to help us ensure correct system text j…
jar-stripe Nov 21, 2024
de5b0c3
replaced own UnixEpoch with DateTimeUtils
jar-stripe Nov 21, 2024
b3512f5
added additional system text json attributes
jar-stripe Nov 21, 2024
70f0327
updated wholesome tests
jar-stripe Nov 25, 2024
ed9ab01
added stj attributes to manually maintained classes
jar-stripe Nov 25, 2024
a158eb5
updated DontSerializeNullDeletedAttrs test to check for STJ equivalent
jar-stripe Nov 25, 2024
6109137
updated attributes for generated classes
jar-stripe Nov 26, 2024
a48e2ca
removed TODO
jar-stripe Nov 26, 2024
c79ed0d
added JsonConverter attributes to interfaces and ExpandableField
jar-stripe Nov 26, 2024
0da3ac5
refactored tests, cleared todos, and cleaned up code
jar-stripe Nov 26, 2024
d5ce297
Merge branch 'master' into jar/coexist-system-text-json
jar-stripe Nov 27, 2024
2767ba8
reverted accidental checkin
jar-stripe Nov 27, 2024
177b59b
Merge branch 'jar/coexist-system-text-json' of github.com:stripe/stri…
jar-stripe Nov 27, 2024
27d6fef
updated generated files
jar-stripe Nov 27, 2024
7e06bd2
added STJMemberSerializationOptIn custom converter factory to impleme…
jar-stripe Nov 28, 2024
fd8e14b
removed JsonInclude from SystemTextJsonUtils HasCorrectAttributes
jar-stripe Nov 28, 2024
de4e1a1
removed temporary TempProfiler class
jar-stripe Nov 28, 2024
6755f42
removed JsonInclude from manually maintained types and added OptIn co…
jar-stripe Nov 28, 2024
33f0560
rewrote STJStripeObjectConverter as a factory, and moved the JsonConv…
jar-stripe Nov 28, 2024
476ef07
removed all updates to generated files; this commit should contain on…
jar-stripe Dec 5, 2024
769340b
generated file updates with STJ support
jar-stripe Dec 5, 2024
ba81e81
removed changes to generated files (again)
jar-stripe Dec 5, 2024
04f886d
empty commit; this should show only manually modified files
jar-stripe Dec 5, 2024
d6f4322
added generated files with STJ support (again)
jar-stripe Dec 5, 2024
a1d5caa
Revert "added generated files with STJ support (again)"
jar-stripe Dec 5, 2024
dbe04ba
Merge remote-tracking branch 'origin/beta' into jar/coexist-system-te…
jar-stripe Dec 5, 2024
682c813
removed old commented code
jar-stripe Dec 5, 2024
68e1b90
added custom converter for V2 events, to ensure lists of polymorphic …
jar-stripe Dec 7, 2024
8b37706
added comments to explain Serialization and RawJObject limitations
jar-stripe Dec 9, 2024
b45793b
Update README.md
jar-stripe Dec 9, 2024
3ff9188
Update README.md
jar-stripe Dec 9, 2024
8d10b56
Merge branch 'beta' into jar/coexist-system-text-json
jar-stripe Dec 9, 2024
b116629
correted mistake in method doc
jar-stripe Dec 9, 2024
86560fc
updated generated code to include system.text.json attributes
jar-stripe Dec 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ customer.RawJObject["secret_parameter"]["secondary"];

```

This is only supported on objects returned directly from the Stripe.net SDK. If you are serializing Stripe objects to JSON you will need to handle undocumented properties separately.

### Writing a plugin

If you're writing a plugin that uses the library, we'd appreciate it if you
Expand Down Expand Up @@ -264,6 +266,54 @@ You can disable this behavior if you prefer:
StripeConfiguration.EnableTelemetry = false;
```

### Serializing Stripe resources to JSON
Stripe resources returned from a Stripe .NET library method can be serialized to a JSON string, which will contain all publicly documented fields for that object (see [Serialization and RawJObject](#serialization-and-rawjobject) below):

#### Newtonsoft Json.NET
```c#
using Newtonsoft.Json;

...

var service = new CustomerService();
var customer = service.Get("cus_1234");

string output = JsonConvert.SerializeObject(customer);
// { "id": "cus_1234", "name": "Jenny Rosen", ... }
```

If you are using .NET 6 or above, you can also use System.Text.Json to serialize the same string value:
#### System.Text.Json
```c#
using System.Text.Json;
...
var service = new CustomerService();
var customer = service.Get("cus_1234");

string output = JsonSerializer.Serialize(customer);
// { "id": "cus_1234", "name": "Jenny Rosen", ... }
```

#### ASP.NET
If you are using .NET 6 or have installed the [Microsoft.AspNetCore.Mvc.NewtonsoftJson][https://www.nuget.org/packages/microsoft.aspnetcore.mvc.newtonsoftjson] package, you can return Stripe objects from ASP.NET controller methods:

```c#
using System.Text.Json;

public class HomeController : Controller
{
...
public IActionResult Index()
{
return Json(_client.V1.Customers.List());
// { "data": [{"id": "cus_1234", "name": "Jenny Rosen"}, ...], "has_more": false }
}
}
```

#### Serialization and RawJObject
The [RawJObject property](#properties) is ignored on serialization in both Json.NET and System.Text.Json, which means that if you serialize a SDK response to a JSON string and the deserialize it back into a Stripe object, this property may be null or empty. If you rely on `RawJObject` you will need to serialize those values separately.

### Beta SDKs

Stripe has features in the beta phase that can be accessed via the beta version of this package.
Expand Down
17 changes: 17 additions & 0 deletions src/Stripe.net/Entities/AccountLinks/AccountLink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ namespace Stripe
using System;
using Newtonsoft.Json;
using Stripe.Infrastructure;
#if NET6_0_OR_GREATER
using STJS = System.Text.Json.Serialization;
#endif

/// <summary>
/// Account Links are the means by which a Connect platform grants a connected account
Expand All @@ -18,26 +21,40 @@ public class AccountLink : StripeEntity<AccountLink>, IHasObject
/// String representing the object's type. Objects of the same type share the same value.
/// </summary>
[JsonProperty("object")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("object")]
#endif
public string Object { get; set; }

/// <summary>
/// Time at which the object was created. Measured in seconds since the Unix epoch.
/// </summary>
[JsonProperty("created")]
[JsonConverter(typeof(UnixDateTimeConverter))]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("created")]
[STJS.JsonConverter(typeof(STJUnixDateTimeConverter))]
#endif
public DateTime Created { get; set; } = Stripe.Infrastructure.DateTimeUtils.UnixEpoch;

/// <summary>
/// The timestamp at which this account link will expire.
/// </summary>
[JsonProperty("expires_at")]
[JsonConverter(typeof(UnixDateTimeConverter))]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("expires_at")]
[STJS.JsonConverter(typeof(STJUnixDateTimeConverter))]
#endif
public DateTime ExpiresAt { get; set; } = Stripe.Infrastructure.DateTimeUtils.UnixEpoch;

/// <summary>
/// The URL for the account link.
/// </summary>
[JsonProperty("url")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("url")]
#endif
public string Url { get; set; }
}
}
36 changes: 36 additions & 0 deletions src/Stripe.net/Entities/AccountNotices/AccountNotice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ namespace Stripe
using System.Collections.Generic;
using Newtonsoft.Json;
using Stripe.Infrastructure;
#if NET6_0_OR_GREATER
using STJS = System.Text.Json.Serialization;
#endif

/// <summary>
/// A notice to a Connected account. Notice can be sent by Stripe on your behalf or you can
Expand All @@ -20,45 +23,68 @@ public class AccountNotice : StripeEntity<AccountNotice>, IHasId, IHasMetadata,
/// Unique identifier for the object.
/// </summary>
[JsonProperty("id")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("id")]
#endif
public string Id { get; set; }

/// <summary>
/// String representing the object's type. Objects of the same type share the same value.
/// </summary>
[JsonProperty("object")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("object")]
#endif
public string Object { get; set; }

/// <summary>
/// Time at which the object was created. Measured in seconds since the Unix epoch.
/// </summary>
[JsonProperty("created")]
[JsonConverter(typeof(UnixDateTimeConverter))]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("created")]
[STJS.JsonConverter(typeof(STJUnixDateTimeConverter))]
#endif
public DateTime Created { get; set; } = Stripe.Infrastructure.DateTimeUtils.UnixEpoch;

/// <summary>
/// When present, the deadline for sending the notice to meet the relevant regulations.
/// </summary>
[JsonProperty("deadline")]
[JsonConverter(typeof(UnixDateTimeConverter))]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("deadline")]
[STJS.JsonConverter(typeof(STJUnixDateTimeConverter))]
#endif
public DateTime? Deadline { get; set; }

/// <summary>
/// Information about the email when sent.
/// </summary>
[JsonProperty("email")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("email")]
#endif
public AccountNoticeEmail Email { get; set; }

/// <summary>
/// Information about objects related to the notice.
/// </summary>
[JsonProperty("linked_objects")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("linked_objects")]
#endif
public AccountNoticeLinkedObjects LinkedObjects { get; set; }

/// <summary>
/// Has the value <c>true</c> if the object exists in live mode or the value <c>false</c> if
/// the object exists in test mode.
/// </summary>
[JsonProperty("livemode")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("livemode")]
#endif
public bool Livemode { get; set; }

/// <summary>
Expand All @@ -67,6 +93,9 @@ public class AccountNotice : StripeEntity<AccountNotice>, IHasId, IHasMetadata,
/// object in a structured format.
/// </summary>
[JsonProperty("metadata")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("metadata")]
#endif
public Dictionary<string, string> Metadata { get; set; }

/// <summary>
Expand All @@ -89,6 +118,9 @@ public class AccountNotice : StripeEntity<AccountNotice>, IHasId, IHasMetadata,
/// <c>issuing.dispute_won</c>.
/// </summary>
[JsonProperty("reason")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("reason")]
#endif
public string Reason { get; set; }

/// <summary>
Expand All @@ -97,6 +129,10 @@ public class AccountNotice : StripeEntity<AccountNotice>, IHasId, IHasMetadata,
/// </summary>
[JsonProperty("sent_at")]
[JsonConverter(typeof(UnixDateTimeConverter))]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("sent_at")]
[STJS.JsonConverter(typeof(STJUnixDateTimeConverter))]
#endif
public DateTime? SentAt { get; set; }
}
}
12 changes: 12 additions & 0 deletions src/Stripe.net/Entities/AccountNotices/AccountNoticeEmail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
namespace Stripe
{
using Newtonsoft.Json;
#if NET6_0_OR_GREATER
using STJS = System.Text.Json.Serialization;
#endif

public class AccountNoticeEmail : StripeEntity<AccountNoticeEmail>
{
Expand All @@ -10,18 +13,27 @@ public class AccountNoticeEmail : StripeEntity<AccountNoticeEmail>
/// Compliance has approved for use.
/// </summary>
[JsonProperty("plain_text")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("plain_text")]
#endif
public string PlainText { get; set; }

/// <summary>
/// Email address of the recipient.
/// </summary>
[JsonProperty("recipient")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("recipient")]
#endif
public string Recipient { get; set; }

/// <summary>
/// Subject of the email.
/// </summary>
[JsonProperty("subject")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("subject")]
#endif
public string Subject { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@
namespace Stripe
{
using Newtonsoft.Json;
#if NET6_0_OR_GREATER
using STJS = System.Text.Json.Serialization;
#endif

public class AccountNoticeLinkedObjects : StripeEntity<AccountNoticeLinkedObjects>
{
/// <summary>
/// Associated <a href="https://stripe.com/docs/api/capabilities">Capability</a>.
/// </summary>
[JsonProperty("capability")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("capability")]
#endif
public string Capability { get; set; }

/// <summary>
Expand All @@ -17,12 +23,18 @@ public class AccountNoticeLinkedObjects : StripeEntity<AccountNoticeLinkedObject
/// Underwriting Record</a>.
/// </summary>
[JsonProperty("issuing_credit_underwriting_record")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("issuing_credit_underwriting_record")]
#endif
public string IssuingCreditUnderwritingRecord { get; set; }

/// <summary>
/// Associated <a href="https://stripe.com/docs/api/issuing/disputes">Issuing Dispute</a>.
/// </summary>
[JsonProperty("issuing_dispute")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("issuing_dispute")]
#endif
public string IssuingDispute { get; set; }
}
}
22 changes: 22 additions & 0 deletions src/Stripe.net/Entities/AccountSessions/AccountSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ namespace Stripe
using System;
using Newtonsoft.Json;
using Stripe.Infrastructure;
#if NET6_0_OR_GREATER
using STJS = System.Text.Json.Serialization;
#endif

/// <summary>
/// An AccountSession allows a Connect platform to grant access to a connected account in
Expand All @@ -23,12 +26,18 @@ public class AccountSession : StripeEntity<AccountSession>, IHasObject
/// String representing the object's type. Objects of the same type share the same value.
/// </summary>
[JsonProperty("object")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("object")]
#endif
public string Object { get; set; }

/// <summary>
/// The ID of the account the AccountSession was created for.
/// </summary>
[JsonProperty("account")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("account")]
#endif
public string Account { get; set; }

/// <summary>
Expand All @@ -45,23 +54,36 @@ public class AccountSession : StripeEntity<AccountSession>, IHasObject
/// handled.
/// </summary>
[JsonProperty("client_secret")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("client_secret")]
#endif
public string ClientSecret { get; set; }

[JsonProperty("components")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("components")]
#endif
public AccountSessionComponents Components { get; set; }

/// <summary>
/// The timestamp at which this AccountSession will expire.
/// </summary>
[JsonProperty("expires_at")]
[JsonConverter(typeof(UnixDateTimeConverter))]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("expires_at")]
[STJS.JsonConverter(typeof(STJUnixDateTimeConverter))]
#endif
public DateTime ExpiresAt { get; set; } = Stripe.Infrastructure.DateTimeUtils.UnixEpoch;

/// <summary>
/// Has the value <c>true</c> if the object exists in live mode or the value <c>false</c> if
/// the object exists in test mode.
/// </summary>
[JsonProperty("livemode")]
#if NET6_0_OR_GREATER
[STJS.JsonPropertyName("livemode")]
#endif
public bool Livemode { get; set; }
}
}
Loading
Loading