diff --git a/src/Stripe.net/Entities/_base/StripeEntity.cs b/src/Stripe.net/Entities/_base/StripeEntity.cs index c5287e4f4c..6e9916463a 100644 --- a/src/Stripe.net/Entities/_base/StripeEntity.cs +++ b/src/Stripe.net/Entities/_base/StripeEntity.cs @@ -4,11 +4,51 @@ namespace Stripe using System.Reflection; using System.Runtime.CompilerServices; using Newtonsoft.Json; + using Newtonsoft.Json.Linq; using Stripe.Infrastructure; [JsonObject(MemberSerialization.OptIn)] public abstract class StripeEntity : IStripeEntity { + [JsonIgnore] + private JObject rawJObject; + + /// + /// Gets the raw JObject exposed by the Newtonsoft.Json library. + /// This can be used to access properties that are not directly exposed by Stripe's .NET + /// library. + /// + /// + /// You should always prefer using the standard property accessors whenever possible. This + /// accessor is not considered fully stable and might change or be removed in future + /// versions. + /// + /// The raw JObject. + [JsonIgnore] + public JObject RawJObject + { + get + { + // Lazily initialize the object the first time the getter is called. + if (this.rawJObject == null) + { + if (this.StripeResponse == null) + { + return null; + } + + this.rawJObject = JObject.Parse(this.StripeResponse.Content); + } + + return this.rawJObject; + } + + protected set + { + this.rawJObject = value; + } + } + [JsonIgnore] public StripeResponse StripeResponse { get; set; } diff --git a/src/StripeTests/Entities/_base/StripeEntityTest.cs b/src/StripeTests/Entities/_base/StripeEntityTest.cs index 95b89f9a5b..097c9228a4 100644 --- a/src/StripeTests/Entities/_base/StripeEntityTest.cs +++ b/src/StripeTests/Entities/_base/StripeEntityTest.cs @@ -5,8 +5,14 @@ namespace StripeTests using Stripe.Infrastructure; using Xunit; - public class StripeEntityTest + public class StripeEntityTest : BaseStripeTest { + public StripeEntityTest( + StripeMockFixture stripeMockFixture) + : base(stripeMockFixture) + { + } + [Fact] public void FromJsonAuto() { @@ -141,6 +147,29 @@ public void ExpandableAccessors_Id_DoesNotResetExistingExpandedObjectIfIdIsSame( Assert.Equal(42, o.Nested.Bar); } + [Fact] + public void RawJObject() + { + var service = new SubscriptionService(this.StripeClient); + var subscription = service.Get("sub_123"); + + Assert.NotNull(subscription); + + // Access `id`, a string element + Assert.Equal(subscription.Id, subscription.RawJObject["id"]); + + // Access `created`, a number element + Assert.Equal(subscription.Created, subscription.RawJObject["created"]); + + // Access `plan[id]`, a nested string element + Assert.Equal(subscription.Plan.Id, subscription.RawJObject["plan"]["id"]); + + // Access `items[data][0][id]`, a deeply nested string element + Assert.Equal( + subscription.Items.Data[0].Id, + subscription.RawJObject["items"]["data"][0]["id"]); + } + private class TestEntity : StripeEntity { [JsonProperty("integer")]