Setup: Spring Modulith 2.0.6, Spring Boot 4.0.6, Java 21.
spring-modulith-apt extracts Javadoc into target/generated-spring-modulith/javadoc.json, and Documenter.writeDocumentation() parses that file with org.springframework.boot.json.BasicJsonParser (via the Asciidoctor static initializer → SpringModulithDocumentationSource). BasicJsonParser is explicitly documented as not fully JSON-compliant, and real-world Javadoc easily produces valid JSON it cannot parse — which makes canvas generation fail for the whole project:
java.lang.ExceptionInInitializerError
at org.springframework.modulith.docs.Asciidoctor.getSpringModulithDocsSource(Asciidoctor.java:431)
at org.springframework.modulith.docs.Asciidoctor.<clinit>(Asciidoctor.java:59)
at org.springframework.modulith.docs.Documenter.toModuleCanvas(Documenter.java:434)
...
Caused by: org.springframework.boot.json.JsonParseException: Cannot parse JSON
at org.springframework.boot.json.BasicJsonParser.parseList(BasicJsonParser.java:53)
at org.springframework.modulith.docs.SpringModulithDocumentationSource.from(SpringModulithDocumentationSource.java:137)
Minimal reproductions
Both inputs are valid JSON (they parse fine with Jackson / JSON.parse / Python json), and both fail with IllegalStateException: Expecting double-quotes around field names:
BasicJsonParser parser = new BasicJsonParser();
// 1. escaped double quote followed (later) by a comma inside a string value
parser.parseList("[{\"name\":\"x\",\"comment\":\"\\\",.\",\"methods\":[]}]");
// 2. unbalanced curly brace inside a string value, with a subsequent entry
parser.parseList("[{\"k\":\"abre { e nao fecha\"},{\"k\":\"x\"}]");
Real-world Javadoc that triggers each case:
- Quoting a UI message:
... shows the message \"if the e-mail exists, we sent a link\", avoiding enumeration. — the escaped quote plus the comma inside the quoted fragment mis-splits the map entries.
- Any prose containing a lone
{ (or }) — e.g. mentioning literal braces or half-open interval notation combined with braces — breaks the parser's depth tracking across array entries.
In our codebase (~640 documented types), dozens of legitimate Javadoc comments contain double quotes or brace/bracket characters, so writeDocumentation() is effectively unusable without pre-processing.
Suggestion
Parse the APT output with a compliant parser — e.g. Jackson when it is on the classpath (it already is for many Modulith users via spring-modulith-events-jackson) — or escape/normalize on the APT side when writing javadoc.json.
Workaround
We currently re-serialize target/generated-spring-modulith/javadoc.json before invoking the Documenter, replacing ", {, }, [, ] inside comment values — cosmetic in the canvas, but it lets BasicJsonParser through.
Setup: Spring Modulith 2.0.6, Spring Boot 4.0.6, Java 21.
spring-modulith-aptextracts Javadoc intotarget/generated-spring-modulith/javadoc.json, andDocumenter.writeDocumentation()parses that file withorg.springframework.boot.json.BasicJsonParser(via theAsciidoctorstatic initializer →SpringModulithDocumentationSource).BasicJsonParseris explicitly documented as not fully JSON-compliant, and real-world Javadoc easily produces valid JSON it cannot parse — which makes canvas generation fail for the whole project:Minimal reproductions
Both inputs are valid JSON (they parse fine with Jackson /
JSON.parse/ Pythonjson), and both fail withIllegalStateException: Expecting double-quotes around field names:Real-world Javadoc that triggers each case:
... shows the message \"if the e-mail exists, we sent a link\", avoiding enumeration.— the escaped quote plus the comma inside the quoted fragment mis-splits the map entries.{(or}) — e.g. mentioning literal braces or half-open interval notation combined with braces — breaks the parser's depth tracking across array entries.In our codebase (~640 documented types), dozens of legitimate Javadoc comments contain double quotes or brace/bracket characters, so
writeDocumentation()is effectively unusable without pre-processing.Suggestion
Parse the APT output with a compliant parser — e.g. Jackson when it is on the classpath (it already is for many Modulith users via
spring-modulith-events-jackson) — or escape/normalize on the APT side when writingjavadoc.json.Workaround
We currently re-serialize
target/generated-spring-modulith/javadoc.jsonbefore invoking theDocumenter, replacing",{,},[,]insidecommentvalues — cosmetic in the canvas, but it letsBasicJsonParserthrough.