-
Notifications
You must be signed in to change notification settings - Fork 468
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
Add omitempty
to JSON field tags on optional fields
#1937
Comments
@m-mattia-m Thank you! I've added this to our internal backlog so we can track and prioritize it alongside our other work. |
👋 Hi @m-mattia-m! Thanks for raising this issue! I'm trying to understand what you mean by
In what sense are they required? I looked at your sample PR #1936 (thanks for putting that together!), but that looks to be addressing the Also, have you looked at how we handle webhooks using |
Hi @mbroshi-stripe 👋 Thanks for facing this issue. If I remember correctly, was my application with the official stripe-go struct not able to bind the request that is made on the object due to missing attributes. So what I meant was that the stripe-go struct expected to get a complete object, but in reality there were three missing attributes. What I tried in the mentioned PR was, that I make the attributes optional because if it's not decelerated as
So I think the I hope it's understandable what I mean. 😬 |
I apologize, but I'm still having trouble understanding this bit:
What does that mean the "struct expected to get a complete object"? Perhaps a code snippet might help me understand what you're trying to accomplish. If I take the provided example in this Issue and just replace |
Now I'm not sure anymore if I have a thinking error, but I still have this error. :) I opened my playground repository m-mattia-m/stripe-go-event-bug-report and started the application on port 8080. Then I started my terminal and logged into Stripe with Now all applications are up and running, and I triggered the first event with
The incoming message looked like this (but as a string). The event payload was also formatted as a string, but I changed it to the JSON format for the better readability. {
"type": "webhook_event",
"endpoint": { "api_version": "2025-01-27.acacia" },
"event_payload": "<see below in collapsed section>",
"http_headers": {
"Accept": "*/*; q=0.5, application/xml",
"Cache-Control": "no-cache",
"Content-Type": "application/json; charset=utf-8",
"Stripe-Signature": "t=1233,v1=asdf1234,v0=asdf1234",
"User-Agent": "Stripe/1.0 (+https://stripe.com/docs/webhooks)"
},
"webhook_conversation_id": "123-wc_asdf",
"webhook_id": "1234-wh_asdf"
}
Whole payload{
"id": "evt_asdf",
"object": "event",
"api_version": "2025-01-27.acacia",
"created": 1738350837,
"data": {
"object": {
"id": "ch_asdf",
"object": "charge",
"amount": 2000,
"amount_captured": 2000,
"amount_refunded": 0,
"application": null,
"application_fee": null,
"application_fee_amount": null,
"balance_transaction": "txn_asdf",
"billing_details": {
"address": {
"city": null,
"country": null,
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": null,
"name": null,
"phone": null
},
"calculated_statement_descriptor": "ACME",
"captured": true,
"created": 1738350837,
"currency": "usd",
"customer": null,
"description": "(created by Stripe CLI)",
"destination": null,
"dispute": null,
"disputed": false,
"failure_balance_transaction": null,
"failure_code": null,
"failure_message": null,
"fraud_details": {
},
"invoice": null,
"livemode": false,
"metadata": {
},
"on_behalf_of": null,
"order": null,
"outcome": {
"advice_code": null,
"network_advice_code": null,
"network_decline_code": null,
"network_status": "approved_by_network",
"reason": null,
"risk_level": "normal",
"risk_score": 54,
"seller_message": "Payment complete.",
"type": "authorized"
},
"paid": true,
"payment_intent": "pi_asdf",
"payment_method": "pm_asdf",
"payment_method_details": {
"card": {
"amount_authorized": 2000,
"authorization_code": null,
"brand": "visa",
"checks": {
"address_line1_check": null,
"address_postal_code_check": null,
"cvc_check": "pass"
},
"country": "US",
"exp_month": 1,
"exp_year": 2026,
"extended_authorization": {
"status": "disabled"
},
"fingerprint": "asdf",
"funding": "credit",
"incremental_authorization": {
"status": "unavailable"
},
"installments": null,
"last4": "4242",
"mandate": null,
"multicapture": {
"status": "unavailable"
},
"network": "visa",
"network_token": {
"used": false
},
"network_transaction_id": "12345",
"overcapture": {
"maximum_amount_capturable": 2000,
"status": "unavailable"
},
"regulated_status": "unregulated",
"three_d_secure": null,
"wallet": null
},
"type": "card"
},
"radar_options": {
},
"receipt_email": null,
"receipt_number": null,
"receipt_url": "https://pay.stripe.com/receipts/payment/asdf",
"refunded": false,
"review": null,
"shipping": {
"address": {
"city": "San Francisco",
"country": "US",
"line1": "510 Townsend St",
"line2": null,
"postal_code": "94103",
"state": "CA"
},
"carrier": null,
"name": "Jenny Rosen",
"phone": null,
"tracking_number": null
},
"source": null,
"source_transfer": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"status": "succeeded",
"transfer_data": null,
"transfer_group": null
}
},
"livemode": false,
"pending_webhooks": 2,
"request": {
"id": "req_asdf",
"idempotency_key": "1234567890-asdf-asdf-asdf-asdf1234"
},
"type": "charge.succeeded"
} Since I can't see the response in the CLI, I sent the payload manually with Postman to Environment: |
@m-mattia-m Did you try replacing |
@mbroshi-stripe, You are right. I got a 204 too after replacing the input structs. However, when I checked the incoming input struct with the debugger, it's an empty object. I also get the same output after changing StripeWebhookEventRequest to a struct like this: type MyRandomTestStruct struct {
firstname string `json:"firstname"`
lastname string `json:"lastname"`
} Normally you define incoming requests in Huma with a body if you want to send a payload. For this reason, I think Huma treats every request like this because they don't have the expected attributes like headers, body, ... that Huma wants to parse. I think my demo repository handles the correct behavior from Huma which throws an error because the payload doesn't fulfill all the requirements. |
Thanks @m-mattia-m for the explanation! I was not familiar with Huma, but I see that it is opinionated on how it validates JSON: https://huma.rocks/features/request-validation/#optional-required. We do not have any plans at the moment to support Huma, so I would recommend using a design to handle incoming webhooks like the example here: https://github.com/stripe-samples/checkout-one-time-payments/blob/main/server/go/server.go#L131-L155. |
@mbroshi-stripe I totally understand if Huma isn't officially supported at the moment, but I wanted to highlight that this seems like a general issue rather than something specific to Huma, since the standard go library works the same way.
The core issue is that JSON attributes are not required by default, whereas Go structures expect all attributes unless specified otherwise. As a result, attributes that aren't required should be explicitly marked as optional in Go. For instance, the account attribute is defined as a "nullable string." If I understand correctly, your API omits nullable objects, meaning this attribute isn't included in the JSON. However, your SDK treats it as required. Adding Let me know if I'm misunderstanding anything here - just wanted to bring this up for discussion. :) |
To be clear, That said, I've also in the past considered adding |
Event
object are not optionalomitempty
to JSON field tags on optional fields
Ok sorry, I've never checked the content type because I thought since the payload is in JSON format it must be |
Describe the bug
When my API receives a webhook request from Stripe via the CLI, I got the error
expected required property account to be present
and the location attribute is:body
. After I created a manual request with the same body and added the attributeaccount
(which is an empty string) I got the same error for the attribute:previous_attributes
at thebody.data
location. After adding this element as well, it worked.I checked the stripe docs and saw that the
account
attribute is anullable string
. Theprevious_attributes
is anullable map
. However, the stripe-go-sdk regard these attributes as required attributes and not as optional.Consider this pull request: #1936
To Reproduce
stripe listen --forward-to localhost:8081/webhook
)Check out this repository (m-mattia-m/stripe-go-event-bug-report) for a working example and all the request and response details (cURL, JSON, ...).
Expected behavior
I expect that I can use the stripe.Event object to bind the JSON and it works fine. It should also be able to handle optional attributes like
account
orprevious_attributes
.Code snippets
OS
macOS 15.0.1
Go version
Go 1.21
stripe-go version
v80.2.0
API version
2022-11-15
Additional context
No response
The text was updated successfully, but these errors were encountered: