Skip to content

Write parameter domains as names in JSONProducer - #206

Merged
alexeid merged 1 commit into
masterfrom
fix/jsonproducer-domain
Nov 6, 2026
Merged

alexeid merged 1 commit into
masterfrom
fix/jsonproducer-domain

Conversation

@walterxie

Copy link
Copy Markdown
Member

Fixes #205.

JSONProducer wrote each parameter's domain as an object the first time (domain: {spec: "beast.base.spec.domain.PositiveReal"}) and as "@null" after that. As a result, no BEAST 3 model with spec parameters could be written as JSON and read back.

Changes (JSONProducer.inputToJSON)

  • New Domain case: writes the short class name, domain: "PositiveReal", as XMLProducer does (XMLProducer.java:1141).
  • Domains a class sets itself are not written. SimplexParam fixes UnitInterval in its constructors, and JSONParser rejects a value for an input that is no longer at its default (Multiple entries for non-list input domain). A domain is skipped when a default-constructed object of the same class already holds it, and it differs from the input's declared default. All other domains are still written explicitly, including domain: "Real".

Tests

New beast.base.parser.JSONProducerTest. All 5 tests fail without the fix.

Test Checks
domainIsWrittenAsShortName domain: "PositiveReal" / "Real"; no domain objects, no "@null"
sharedDomainIsWrittenForEveryParameter two parameters sharing PositiveReal both get it (the second used to be "@null")
roundTripKeepsDomains write → JSONParser.parseFragment → each parameter has the same domain object
roundTripKeepsIntegerDomain the same for IntVectorParam / NonNegativeInt
domainFixedByTheClassIsNotWritten SimplexParam writes no domain and parses back with UnitInterval

Validation

JSONProducer had no case for Domain values: a domain (a shared singleton)
was written as {spec: "...PositiveReal"} the first time and "@null" after
that, which JSONParser cannot read. Write the short name
(domain: "PositiveReal"), as XMLProducer does.

Do not write a domain that the class sets itself (SimplexParam fixes
UnitInterval): JSONParser rejects a value for an input that is no longer
at its default.

Adds JSONProducerTest: domains written as names, a shared domain written
for every parameter, and JSON round trips keeping real, integer and
simplex domains.

@alexeid alexeid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Walter, this fixes #205 cleanly, and the tests cover the cases that matter. I checked that the new tests pass with the fix and fail without it. Two notes for later, not blocking:

  1. isDomainFixedByClass default-constructs each class by reflection and treats any exception as "not fixed". That works, but it would quietly misjudge a class whose no-argument constructor fails or has side effects. The underlying oddity is JSONParser rejecting a domain equal to the one the class already set ("Multiple entries for non-list input"); relaxing that in the parser would make this check unnecessary.
  2. XMLProducer may have the same SimplexParam issue (writing domain="UnitInterval" for a class that fixes it). Worth checking whether XMLParser accepts that.

@alexeid
alexeid merged commit 356842a into master Nov 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JSONProducer writes parameter domains that BEAST 3 cannot read back

2 participants