Skip to content

feat(responses): make omittable FMP response members optional across SDKs - #394

Merged
benbenbang merged 3 commits into
mainfrom
feat/368-misc-nullable
Sep 30, 2026
Merged

benbenbang merged 3 commits into
mainfrom
feat/368-misc-nullable

Conversation

@benbenbang

@benbenbang benbenbang commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

FMP can send null for a number of response members, which previously caused decode failures because those members were required and non-null. This change makes every such member optional across the Rust, Python, and Go SDKs so decoding no longer fails when the provider omits a value, while still requiring the member to be present.

What changed:

  • Made nullable members optional in news, market hours, ESG, and congressional responses (NewsArticle image/site, ExchangeHoliday is_closed, EsgDisclosure company_name/form_type, EsgRating company_name, CongressionalMemberProfile image).
  • Made CryptocurrencyListing icoDate, circulatingSupply, and totalSupply optional, decoding empty ICO dates to none and preserving integral supply round-tripping.
  • Made fundraising and SEC filing members optional (CrowdfundingOffering issuer/intermediary/offering fields, RegulationDOffering revenueRange and equity flag, SecCompanyProfile fiscalYearEnd/employees, SecCompanySearchResult phoneNumber).
  • Applied consistent decode semantics: Rust uses required_option deserializers and Go uses jsontext.Value shadows so a null value maps to None/nil while a missing member still fails.
  • Updated Python pyo3 models, .pyi stubs, and the typecheck contract to expose the new Optional types.
  • Added Rust, Python, and Go parity tests covering null-decodes-to-none and missing-member-still-fails, and updated existing assertions.

BREAKING CHANGE: Members FMP can omit on NewsArticle, ExchangeHoliday, EsgDisclosure, EsgRating, CongressionalMemberProfile, CryptocurrencyListing, CrowdfundingOffering, RegulationDOffering, SecCompanyProfile, and SecCompanySearchResult are now optional (Option / pointer / Optional); consumers must handle None.

close #368

…onal members optional

Members that FMP can send as null are now optional so decoding no longer
fails on absent values. Consumers must handle None for these members.

**Optional member changes:**
* `NewsArticle.image` and `NewsArticle.site` are now optional.
* `ExchangeHoliday.is_closed` is now optional.
* `EsgDisclosure.company_name` and `EsgDisclosure.form_type` are now optional.
* `EsgRating.company_name` is now optional.
* `CongressionalMemberProfile.image` is now optional.

**Decode behaviour:**
* These members are still required to be present, but a null value decodes to None/nil rather than raising a decode error.
* The Rust responses use `required_option` deserializers; the Go SDK uses `jsontext.Value` shadows that reject missing members and map null to nil.

**Bindings and tests:**
* Updated the Python `.pyi` stubs and pyo3 models to expose the optional types, and adjusted the typecheck contract.
* Added Rust, Python, and Go parity tests covering null-decodes-to-none while a missing member still fails.

BREAKING CHANGE: NewsArticle, ExchangeHoliday, EsgDisclosure, EsgRating and CongressionalMemberProfile members FMP can omit are now optional (Option / pointer / Optional); handle None.
The provider can omit `icoDate`, `circulatingSupply`, and `totalSupply`
from a cryptocurrency listing, so these members are now optional across
the SDKs instead of required non-null values.

**Rust wire model:**
* `CryptocurrencyListing` in `crates/libfmp` now types `ico_date`,
  `circulating_supply`, and `total_supply` as `Option`, keeping the
  members required but nullable and decoding an empty `icoDate` to
  `None` via `empty_or_null_date`.
* Supply members serialize through `integral_f64::serialize_option` so
  integral values still round-trip as integers.

**Python bindings:**
* The `CryptocurrencyListing` model and its stubs expose the three
  members as `Option` / `typing.Optional`, mapping the inner date only
  when present.

**Go SDK:**
* `CryptocurrencyListing` holds pointer members and decodes null or
  empty values to `nil` through a `jsontext.Value` shadow, while still
  rejecting missing members.

**Tests:**
* Added coverage in all three SDKs for null supplies and empty ICO
  dates decoding to `None` / `nil`, and updated existing assertions to
  the optional representation.

BREAKING CHANGE: CryptocurrencyListing members FMP can omit are now optional (Option / pointer / Optional); handle None.
…ptional

Members that FMP can send as null on older filings are now decoded as
optional instead of required, so callers must handle the absent case.

**Model changes:**
* `CrowdfundingOffering` makes `issuerWebsite`, `intermediaryCompanyName`, `intermediaryCommissionFileNumber`, `compensationAmount`, `financialInterest`, `securityOfferedType`, `overSubscriptionAllocationType`, and `offeringDeadlineDate` optional.
* `RegulationDOffering` makes `revenueRange` and `securitiesOfferedAreOfEquityType` optional.
* `SecCompanyProfile` makes `fiscalYearEnd` and `employees` optional.
* `SecCompanySearchResult` makes `phoneNumber` optional.

**Decoding behaviour:**
* libfmp uses `required_option` so these members must be present but decode a JSON null to `None`; the Go SDK mirrors this with `jsontext.Value` shadows that reject a missing member and map null to nil.
* The Python `.pyi` stubs and pyo3 models expose the new `Optional` types, and the typecheck contract now treats `offering_deadline_date` as nullable.

**Tests:**
* Added libfmp, Go parity, and Python tests asserting each new nullable member decodes null to None/nil while a missing member still fails.

BREAKING CHANGE: CrowdfundingOffering, RegulationDOffering, SecCompanyProfile and SecCompanySearchResult members FMP can omit are now optional (Option / pointer / Optional); handle None.
@benbenbang
benbenbang enabled auto-merge (rebase) September 30, 2026 14:36
@github-actions github-actions Bot added the enhancement New feature or request label Sep 30, 2026
@benbenbang
benbenbang merged commit 4850095 into main Sep 30, 2026
9 of 16 checks passed
@benbenbang
benbenbang deleted the feat/368-misc-nullable branch September 30, 2026 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat!: nullable members for values FMP can omit (1.2.0)

1 participant