Add CSL-JSON import endpoint for correct entry-type mapping#16151
Conversation
Extend `POST /libraries/{id}/entries` to accept CSL-JSON
(`application/vnd.citationstyles.csl+json`), so browser translators (and any
CSL-JSON producer) can hand items to JabRef and get the correct entry type
instead of a flat @Article.
Rather than a bespoke Zotero-itemType -> BibTeX map (rejected by ADR 0064),
reuse the merged citation-js-based CSL mapping (`CSLItemTypeDefinitions`,
PR #15946): extract the CSL-JSON -> BibEntry core from
`ZoteroCitationMarkParser.toBibEntry` into a new public
`parseCslJsonItems(String)` that accepts a bare CSL item or an array.
`EntriesResource.addCslJson` serialises the mapped entries to BibTeX and
appends them via the existing `AppendBibTeXToLibrary` command, preserving
duplicate handling and group assignment. Entries carry no citation key so
JabRef generates keys on import. Freshly built entries are written with
reformat=true (empty parsed serialisation otherwise writes nothing).
Tests: type/field mapping and array/object/blank/invalid handling in
`ZoteroCitationMarkParserTest`; endpoint conversion + 400 paths in
`EntriesResourceTest`.
Related to #15875
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR Summary by QodoAdd CSL-JSON import support to POST /libraries/{id}/entries
AI Description
Diagram
High-Level Assessment
Files changed (5)
|
Code Review by Qodo
1.
|
The isJsonArray/isJsonObject guards already ensure Gson returns non-null, so the != null checks were unreachable; removing them also satisfies the no-null-check style rule. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CSL-JSON that sets optional properties explicitly to null ("type": null,
"author": null, "issued": null, "issued": {"date-parts": null}) crashed the
import path with an NPE (Gson overwrites the field defaults with null, and the
immutable CSL mapping tables reject a null key lookup), surfacing as HTTP 500.
Normalise type/author/issued and guard date-parts before use. Add a
parameterised regression test covering each null shape.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the traditional @param tag with a Markdown sentence, per the project's Markdown-Javadoc guideline for new docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use @CsvSource with a `|` delimiter (JSON keeps its commas) so the null-field cases read as a table of input -> expected entry type, and clean up the provider imports. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace list.get(0) with list.getFirst() per SequencedCollection recipe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nMarkParser.java Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
|
Your pull request conflicts with the target branch. Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line. |
* upstream/main: fix dependency configuration for jlatexmath (JabRef#16202) Open add-file link dialog when File field added; add on empty-area double-click (JabRef#16192) New Crowdin updates (JabRef#16196) Chore(deps): Bump org.postgresql:postgresql from 42.7.12 to 42.7.13 in /versions (JabRef#16194) Chore(deps): Bump org.gradlex:java-module-packaging in /build-logic (JabRef#16193) Add CSL-JSON import endpoint for correct entry-type mapping (JabRef#16151) Increase arrow button size in Entry Preview preferences tab (JabRef#16063) Add focus-triggered remove button for empty optional fields in entry editor (JabRef#16185) Render entry preview with html-to-node and remove javafx.web (JabRef#16145) Fix arrow-text spacing in entry editor collapsible sections (JabRef#16184) SLR: scopus raw query support (JabRef#16103) Update crowdin config to support CLI (JabRef#16182) 🤖 Fix entry editor fields growing wider than available space for long values (JabRef#16181) Fix file field editor: button placement, sizing, live refresh (JabRef#16172) Add madrlint MADR linter to test workflow (JabRef#16168)
Related issues and pull requests
Related to #15875 (Zotero compatibility) and ADR #15907. There is no dedicated issue requesting this HTTP endpoint, so no
Closes.PR Description
The HTTP import endpoint
POST /libraries/{id}/entriesnow also accepts CSL-JSON (application/vnd.citationstyles.csl+json), so a CSL-JSON producer (e.g. a browser translator) can hand items to JabRef and get the correct entry type — conference paper →@InProceedings, book chapter →@InBook, thesis →@Thesis, report →@Report, web page →@Online— instead of a flat@article. Rather than a bespoke Zotero-itemType→BibTeX map (the option rejected in ADR 0064), it reuses the merged citation-js-based CSL mapping (CSLItemTypeDefinitions, #15946) by extracting the CSL-JSON →BibEntrycore out ofZoteroCitationMarkParserinto a new publicparseCslJsonItems(String), and appends the mapped entries through the existingAppendBibTeXToLibrarycommand (duplicate handling and group assignment preserved).Steps to test
Open a library in JabRef and enable the HTTP server.
POST a CSL item to the running server:
Expect
204 No Content, and a new@InProceedingsentry in the library withbooktitle = {Proc. of Test}, author Jane Doe, year 2021 — not@article.Posting an array of items adds several entries; blank or unparseable bodies return
400.AI usage
Claude Code (model claude-opus-4-8). All code reviewed and owned by the submitter.
AI CHECKLIST.md walkthrough
1. Code self-review
Nullability and control flow
== null/!= nullchecks in new code (guarded byisJsonArray()/isJsonObject()so Gson results are non-null).Objects.requireNonNull(...).@NullMarked— no new class; edits sit in existing (non-@NullMarked) files.Optionalconsumed withifPresent/map— noorElse(unused)/isPresent()+get().StringUtil.isBlank(...)used for the blank-body checks.Exceptions
catch (Exception e)— onlyJsonParseException | NumberFormatException | NoSuchElementException.throw new RuntimeException(...)/IllegalStateException(...); the endpoint throws JAX-RSBadRequestException.LOGGER.debug("...", e)).Style and idioms
BibEntrybuilt with withers (withField,withCitationKey,withDate).List.of(), text blocks, switch expressions in existing code).Patternconstant (existingYEAR_PATTERN).BackgroundTask— not applicable, no background work.[BibEntry]/`code`, not{@link}/{@code}.User-facing text
400reasons, not localized UI text (consistent with sibling endpoints in the same class).Security
text/htmlresponse; error messages are plain-text HTTP reasons.Tests
org.jabref.logicbehavior change covered —ZoteroCitationMarkParserTest(mapping, array/object/blank/invalid) andEntriesResourceTest(endpoint convert + 400 paths).assertEquals/assertTrue, no AssertJ, no@DisplayName, exceptions propagate.2. Verification commands
./gradlew :jablib:check(full) — ran the relevant subsets below instead../gradlew :jablib:checkstyleMain checkstyleTest :jabsrv:checkstyleMain checkstyleTest— pass../gradlew :jablib:modernizer :jabsrv:modernizer— pass../gradlew :rewriteDryRun— fails on pre-existing parse problems in unrelatedjabguifiles; the changedjablib/jabsrvfiles pass checkstyle (same style)../gradlew javadoc— not run.npx markdownlint-cli2— only a one-lineCHANGELOG.mdaddition matching existing format.3. Documentation
CHANGELOG.mdentry added (end-user wording), linked to this PR after creation.docs/requirementsarea change.4. Pull request
PULL_REQUEST_TEMPLATE.md, sections filled.TODO→real PR link done.Checklist
CHANGELOG.mdin a way that can be understood by the average user (if change is visible to the user)