From 21f5e3aad1948e062ffd97db47c8d56f16ae89a3 Mon Sep 17 00:00:00 2001 From: Eric Deandrea Date: Thu, 22 Oct 2026 12:20:35 -0400 Subject: [PATCH 1/3] feat(api): expose PDF heading hierarchy options in ConvertDocumentOptions Introduce HeadingHierarchyOptions with all docling-serve fields except enabled (which is derived from the presence of this options object). Add a derived doPdfHeadingHierarchy() getter that returns true when headingHierarchyOptions is non-null. Add unit tests for both options classes and a real-client integration test that verifies heading levels are inferred from PDF numbering. Update serve-api.md documentation to list the new option. Closes #754 Signed-off-by: Eric Deandrea --- .../options/ConvertDocumentOptions.java | 27 +++- .../options/HeadingHierarchyOptions.java | 119 ++++++++++++++++++ .../options/ConvertDocumentOptionsTests.java | 46 +++++++ .../options/HeadingHierarchyOptionsTests.java | 117 +++++++++++++++++ .../AbstractDoclingServeClientTests.java | 48 +++++++ docs/src/doc/docs/docling-serve/serve-api.md | 1 + 6 files changed, 354 insertions(+), 4 deletions(-) create mode 100644 docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptions.java create mode 100644 docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptionsTests.java diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptions.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptions.java index b0d6588c..0ebbe0fb 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptions.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptions.java @@ -6,16 +6,16 @@ import org.jspecify.annotations.Nullable; +import ai.docling.serve.api.serialization.DurationSerializationFormat; +import ai.docling.serve.api.serialization.Jackson2DurationSerializer; +import ai.docling.serve.api.serialization.Jackson3DurationSerializer; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import ai.docling.serve.api.serialization.DurationSerializationFormat; -import ai.docling.serve.api.serialization.Jackson2DurationSerializer; -import ai.docling.serve.api.serialization.Jackson3DurationSerializer; - /** * Options for configuring the document conversion process with Docling. */ @@ -233,6 +233,25 @@ public class ConvertDocumentOptions { @Nullable private String vlmPipelineModelApi; + /** + * Whether heading hierarchy inference is enabled. Derived from {@link #headingHierarchyOptions()} + * — {@code true} when options are present, {@code false} otherwise. + */ + @JsonProperty("do_pdf_heading_hierarchy") + public boolean doPdfHeadingHierarchy() { + return headingHierarchyOptions != null; + } + + /** + * Options for inferring PDF section-header levels (H1–H6) from bookmarks, numbering and style. + * Setting this enables heading hierarchy inference; leave it unset to keep all headings at + * level 1. Use the defaults ({@code HeadingHierarchyOptions.builder().build()}) to enable it + * without any fine-tuning. + */ + @JsonProperty("pdf_heading_hierarchy_options") + @Nullable + private HeadingHierarchyOptions headingHierarchyOptions; + public static class Builder { } } diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptions.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptions.java new file mode 100644 index 00000000..5ab726b9 --- /dev/null +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptions.java @@ -0,0 +1,119 @@ +package ai.docling.serve.api.convert.request.options; + +import java.util.List; + +import org.jspecify.annotations.Nullable; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; + +/** + * Options for configuring PDF heading hierarchy inference. + * This class mirrors the Python {@code HeadingHierarchyOptions} from docling-core and is + * used to reconstruct a true heading hierarchy (H1–H6) from PDF bookmarks, outline numbering, + * and visual style instead of emitting all detected section headers flat at level 1. + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@lombok.extern.jackson.Jacksonized +@lombok.Builder(toBuilder = true) +@lombok.Getter +@lombok.ToString +public class HeadingHierarchyOptions { + + /** + * Use the PDF outline / table of contents as the authoritative signal for heading levels. + * + * @param useBookmarks true to use bookmarks, or null for the default (true) + * @return the use-bookmarks flag + */ + @JsonProperty("use_bookmarks") + @Nullable + private Boolean useBookmarks; + + /** + * Use the leading numbering marker of the heading text (e.g., "1.", "1.1.2", "(a)") + * as a signal for heading levels. + * + * @param useNumbering true to use numbering, or null for the default (true) + * @return the use-numbering flag + */ + @JsonProperty("use_numbering") + @Nullable + private Boolean useNumbering; + + /** + * Fall back to the heading's visual style (font size, weight, slant, letter case) when + * neither bookmarks nor numbering provide a level. Requires {@code generate_parsed_pages=True} + * in the pipeline options. + * + * @param useStyle true to use visual style, or null for the default (true) + * @return the use-style flag + */ + @JsonProperty("use_style") + @Nullable + private Boolean useStyle; + + /** + * Refine the style fallback with font weight, slant and all-caps detection. Ignored when + * {@link #useStyle()} is off. + * + * @param useFontStyle true to use font style, or null for the default (true) + * @return the use-font-style flag + */ + @JsonProperty("use_font_style") + @Nullable + private Boolean useFontStyle; + + /** + * Relative difference below which two font sizes count as one. Higher values merge more + * sizes into a single level. + * + * @param styleSizeTolerance the tolerance value, or null for the default (0.05) + * @return the style-size-tolerance value + */ + @JsonProperty("style_size_tolerance") + @Nullable + private Double styleSizeTolerance; + + /** + * Override the numbering-scheme precedence order (highest level first). When null, the + * built-in ordering is used. + * + * @param numberingSchemes the ordered list of scheme names, or null for the default + * @return the numbering-schemes list + */ + @JsonProperty("numbering_schemes") + @JsonSetter(nulls = Nulls.AS_EMPTY) + @lombok.Singular("numberingScheme") + private List numberingSchemes; + + /** + * Deepest heading level assigned by the inference stage; headings deeper than this are + * clamped to this level. + * + * @param maxLevel the maximum level, or null for the default (6) + * @return the max-level value + */ + @JsonProperty("max_level") + @Nullable + private Integer maxLevel; + + /** + * Minimum title similarity (0–1) for a bookmark to claim a heading. Higher values are + * stricter. + * + * @param bookmarkMatchThreshold the threshold, or null for the default (0.8) + * @return the bookmark-match-threshold value + */ + @JsonProperty("bookmark_match_threshold") + @Nullable + private Double bookmarkMatchThreshold; + + /** + * Builder for creating {@link HeadingHierarchyOptions} instances. + */ + public static class Builder { + } +} diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptionsTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptionsTests.java index 0d80f91a..a942db48 100644 --- a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptionsTests.java +++ b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptionsTests.java @@ -39,4 +39,50 @@ void convertDocumentOptionsIsImmutable() { assertThat(options.getOcrLang()).containsExactly("en", "de"); } + @Test + void convertDocumentOptionsWithHeadingHierarchy() { + var hierarchyOptions = HeadingHierarchyOptions.builder() + .useBookmarks(true) + .useNumbering(false) + .maxLevel(4) + .bookmarkMatchThreshold(0.85) + .build(); + + var options = ConvertDocumentOptions.builder() + .headingHierarchyOptions(hierarchyOptions) + .build(); + + assertThat(options) + .extracting( + ConvertDocumentOptions::doPdfHeadingHierarchy, ConvertDocumentOptions::getHeadingHierarchyOptions, o -> o.getHeadingHierarchyOptions().getUseBookmarks(), o -> o + .getHeadingHierarchyOptions().getUseNumbering(), o -> o.getHeadingHierarchyOptions().getMaxLevel(), o -> o.getHeadingHierarchyOptions().getBookmarkMatchThreshold()) + .containsExactly(true, hierarchyOptions, true, false, 4, 0.85); + } + + @Test + void convertDocumentOptionsWithoutHeadingHierarchy() { + var options = ConvertDocumentOptions.builder().build(); + + assertThat(options) + .satisfies(o -> assertThat(o.doPdfHeadingHierarchy()).isFalse()) + .satisfies(o -> assertThat(o.getHeadingHierarchyOptions()).isNull()); + } + + @Test + void convertDocumentOptionsToBuilderWithHeadingHierarchy() { + var hierarchyOptions = HeadingHierarchyOptions.builder() + .maxLevel(3) + .build(); + + var original = ConvertDocumentOptions.builder() + .headingHierarchyOptions(hierarchyOptions) + .build(); + + var rebuilt = original.toBuilder().build(); + + assertThat(rebuilt) + .extracting( + ConvertDocumentOptions::doPdfHeadingHierarchy, ConvertDocumentOptions::getHeadingHierarchyOptions, o -> o.getHeadingHierarchyOptions().getMaxLevel()) + .containsExactly(original.doPdfHeadingHierarchy(), original.getHeadingHierarchyOptions(), 3); + } } diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptionsTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptionsTests.java new file mode 100644 index 00000000..0b12899c --- /dev/null +++ b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptionsTests.java @@ -0,0 +1,117 @@ +package ai.docling.serve.api.convert.request.options; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link HeadingHierarchyOptions}. + */ +class HeadingHierarchyOptionsTests { + + @Test + void createWithAllFields() { + var options = HeadingHierarchyOptions.builder() + .useBookmarks(true) + .useNumbering(false) + .useStyle(true) + .useFontStyle(true) + .styleSizeTolerance(0.1) + .numberingScheme("chapter") + .numberingScheme("section") + .maxLevel(4) + .bookmarkMatchThreshold(0.9) + .build(); + + assertThat(options) + .extracting( + HeadingHierarchyOptions::getUseBookmarks, HeadingHierarchyOptions::getUseNumbering, HeadingHierarchyOptions::getUseStyle, HeadingHierarchyOptions::getUseFontStyle, HeadingHierarchyOptions::getStyleSizeTolerance, HeadingHierarchyOptions::getNumberingSchemes, HeadingHierarchyOptions::getMaxLevel, HeadingHierarchyOptions::getBookmarkMatchThreshold) + .containsExactly(true, false, true, true, 0.1, List.of("chapter", "section"), 4, 0.9); + } + + @Test + void createWithMinimalFields() { + var options = HeadingHierarchyOptions.builder() + .useBookmarks(false) + .build(); + + assertThat(options.getUseBookmarks()).isFalse(); + assertThat(options.getUseNumbering()).isNull(); + assertThat(options.getUseStyle()).isNull(); + assertThat(options.getUseFontStyle()).isNull(); + assertThat(options.getStyleSizeTolerance()).isNull(); + assertThat(options.getNumberingSchemes()).isEmpty(); + assertThat(options.getMaxLevel()).isNull(); + assertThat(options.getBookmarkMatchThreshold()).isNull(); + } + + @Test + void createWithDefaultValues() { + var options = HeadingHierarchyOptions.builder().build(); + + assertThat(options.getUseBookmarks()).isNull(); + assertThat(options.getUseNumbering()).isNull(); + assertThat(options.getUseStyle()).isNull(); + assertThat(options.getUseFontStyle()).isNull(); + assertThat(options.getStyleSizeTolerance()).isNull(); + assertThat(options.getNumberingSchemes()).isEmpty(); + assertThat(options.getMaxLevel()).isNull(); + assertThat(options.getBookmarkMatchThreshold()).isNull(); + } + + @Test + void headingHierarchyOptionsIsImmutable() { + var options = HeadingHierarchyOptions.builder() + .styleSizeTolerance(0.05) + .numberingScheme("chapter") + .build(); + + assertThat(options.getNumberingSchemes()).hasSize(1); + assertThat(options.getNumberingSchemes()).containsExactly("chapter"); + + // Mutating the returned list should not affect the options + assertThatThrownBy(() -> options.getNumberingSchemes().add("section")) + .isInstanceOf(UnsupportedOperationException.class); + } + + @Test + void toBuilderReturnsEquivalentInstance() { + var original = HeadingHierarchyOptions.builder() + .useBookmarks(false) + .maxLevel(3) + .numberingScheme("article") + .numberingScheme("section") + .bookmarkMatchThreshold(0.85) + .build(); + + var rebuilt = original.toBuilder().build(); + + assertThat(rebuilt.getUseBookmarks()).isEqualTo(original.getUseBookmarks()); + assertThat(rebuilt.getUseNumbering()).isEqualTo(original.getUseNumbering()); + assertThat(rebuilt.getUseStyle()).isEqualTo(original.getUseStyle()); + assertThat(rebuilt.getUseFontStyle()).isEqualTo(original.getUseFontStyle()); + assertThat(rebuilt.getStyleSizeTolerance()).isEqualTo(original.getStyleSizeTolerance()); + assertThat(rebuilt.getNumberingSchemes()).containsExactlyElementsOf(original.getNumberingSchemes()); + assertThat(rebuilt.getMaxLevel()).isEqualTo(original.getMaxLevel()); + assertThat(rebuilt.getBookmarkMatchThreshold()).isEqualTo(original.getBookmarkMatchThreshold()); + } + + @Test + void nonNullFieldsOnlyArentOmittedFromJson() { + var options = HeadingHierarchyOptions.builder() + .useBookmarks(true) + .build(); + + assertThat(options.getUseBookmarks()).isTrue(); + assertThat(options.getUseNumbering()).isNull(); + assertThat(options.getUseStyle()).isNull(); + assertThat(options.getUseFontStyle()).isNull(); + assertThat(options.getStyleSizeTolerance()).isNull(); + assertThat(options.getNumberingSchemes()).isEmpty(); + assertThat(options.getMaxLevel()).isNull(); + assertThat(options.getBookmarkMatchThreshold()).isNull(); + } +} diff --git a/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/AbstractDoclingServeClientTests.java b/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/AbstractDoclingServeClientTests.java index d67d38fb..f3aaffef 100644 --- a/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/AbstractDoclingServeClientTests.java +++ b/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/AbstractDoclingServeClientTests.java @@ -67,6 +67,7 @@ import ai.docling.core.DoclingDocument.DocItemLabel; import ai.docling.core.DoclingDocument.FormulaItem; import ai.docling.core.DoclingDocument.ListItem; +import ai.docling.core.DoclingDocument.SectionHeaderItem; import ai.docling.core.DoclingDocument.TableCell; import ai.docling.serve.api.DoclingServeApi; import ai.docling.serve.api.chunk.request.HierarchicalChunkDocumentRequest; @@ -82,6 +83,7 @@ import ai.docling.serve.api.convert.request.CallbackSpec; import ai.docling.serve.api.convert.request.ConvertDocumentRequest; import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions; +import ai.docling.serve.api.convert.request.options.HeadingHierarchyOptions; import ai.docling.serve.api.convert.request.options.ImageRefMode; import ai.docling.serve.api.convert.request.options.OutputFormat; import ai.docling.serve.api.convert.request.options.TableFormerMode; @@ -1259,6 +1261,52 @@ void shouldHandleConversionWithDifferentDocumentOptions() { assertThat(inBodyResponse.getDocument()).isNotNull(); } + @Test + void shouldInferHeadingHierarchyFromPdfNumbering() { + var options = HeadingHierarchyOptions.builder() + .maxLevel(4) + .build(); + + var convOptions = ConvertDocumentOptions.builder() + .toFormat(OutputFormat.JSON) + .headingHierarchyOptions(options) + .build(); + + var request = ConvertDocumentRequest.builder() + .options(convOptions) + .build(); + + var response = getDoclingClient().convertFiles(request, Path.of("src", "test", "resources", "2408.09869.pdf")); + + assertThat(response).isNotNull(); + assertThat(response.getResponseType()).isEqualTo(ResponseType.IN_BODY); + + var inBodyResponse = (InBodyConvertDocumentResponse) response; + assertThat(inBodyResponse.getStatus()).isNotEmpty(); + + DoclingDocument doc = inBodyResponse.getDocument().getJsonContent(); + assertThat(doc).isNotNull(); + + List headers = doc.getTexts().stream() + .filter(SectionHeaderItem.class::isInstance) + .map(SectionHeaderItem.class::cast) + .toList(); + + assertThat(headers).isNotEmpty(); + + // Verify that numbering-based hierarchy was applied (all headings at level 1 would be a + // failure — this PDF has sections like "3.1 PDFbackends" that should be below "3") + assertThat(headers.stream().allMatch(h -> (h.getLevel() != null))) + .as("All section headers should have a level assigned") + .isTrue(); + assertThat(headers.stream().map(SectionHeaderItem::getLevel).distinct().count()) + .as("Multiple heading levels should be present after hierarchy inference") + .isGreaterThan(1); + // There should be at least one level-2 header (e.g. "3.1 PDFbackends") + assertThat(headers) + .anyMatch(h -> "3.1 PDFbackends".equals(h.getText()) && (h.getLevel() >= 2)); + } + @Test void shouldHandleResponseWithDoclingDocument() { ConvertDocumentOptions options = ConvertDocumentOptions.builder() diff --git a/docs/src/doc/docs/docling-serve/serve-api.md b/docs/src/doc/docs/docling-serve/serve-api.md index 5a1cf7a0..e7779a1b 100644 --- a/docs/src/doc/docs/docling-serve/serve-api.md +++ b/docs/src/doc/docs/docling-serve/serve-api.md @@ -177,6 +177,7 @@ Options (`ai.docling.serve.api.convert.request.options.ConvertDocumentOptions`) - OCR (e.g., `doOcr`, `forceOcr`, `ocrEngine`, `ocrLang`) - PDF processing (e.g., `pdfBackend`) - Tables (e.g., `tableMode`, `tableCellMatching`) +- PDF heading hierarchy inference (e.g., `headingHierarchyOptions`) - Pipelines and page ranges (e.g., `pipeline`, `pageRange`) - Timeouts and error behavior (e.g., `documentTimeout`, `abortOnError`) - Enrichments (code/formula/picture), image handling, scaling, page break placeholder From 6c2a8834d6091573b862f09a89d23049b5e6aeec Mon Sep 17 00:00:00 2001 From: Eric Deandrea Date: Thu, 22 Oct 2026 12:20:41 -0400 Subject: [PATCH 2/3] docs(api): add heading hierarchy options to whats-new Add feature note for HeadingHierarchyOptions in the Docling Serve section of what is new. Signed-off-by: Eric Deandrea --- docs/src/doc/docs/whats-new.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/doc/docs/whats-new.md b/docs/src/doc/docs/whats-new.md index 0c149897..eb23be0f 100644 --- a/docs/src/doc/docs/whats-new.md +++ b/docs/src/doc/docs/whats-new.md @@ -26,6 +26,7 @@ Docling Java {{ gradle.project_version }} includes important breaking changes, a ### {{ gradle.project_version }} +* **New `HeadingHierarchyOptions` and `headingHierarchyOptions` on `ConvertDocumentOptions`** — When set, `headingHierarchyOptions` enables PDF section-header level inference from bookmarks, outline numbering and visual style. The helper getter `doPdfHeadingHierarchy()` is derived from the presence of these options (returns `true` when non-null, `false` otherwise), so callers only need to pass the options to enable hierarchy inference. The options class covers all docling-serve fields (`useBookmarks`, `useNumbering`, `useStyle`, `useFontStyle`, `styleSizeTolerance`, `numberingSchemes`, `maxLevel`, `bookmarkMatchThreshold`). * **Breaking: new `DoclingServeApiProvider` SPI** — Implementations are now provided through `ai.docling.serve.api.spi.DoclingServeApiProvider`, which receives an immutable `DoclingServeApiConfig`, so new options can be added without breaking implementations. A provider can declare the options it doesn't honor via `unsupportedOptions()`, to have them ignored, logged or rejected when a caller sets them. `DoclingServeApi` has a new abstract `config()` method. `DoclingServeApiBuilderFactory`, `DoclingServeApi.DoclingApiBuilder` and `DoclingServeApi.toBuilder()` are deprecated for removal; legacy factories are still used when no provider is found. `docling-serve-api` now depends on `slf4j-api`. See [Migrating to `DoclingServeApiProvider`](docling-serve/serve-api-provider-migration.md). * **Breaking: `DoclingServeApi.builder()` returns a `DoclingServeApiBuilder`** — It used to return the builder of the implementation through a generic ` B` return type. Fluent chains and `var` declarations are unaffected, but code declaring the builder type must be updated. Client-specific settings such as `httpClientBuilder` are available from `DoclingServeClient.builder()`, which detects the version of Jackson the same way, and the JSON mapper from `DoclingServeJackson3Client.builder()` / `DoclingServeJackson2Client.builder()`, which are now public. An API can be copied with `api.config().toBuilder()`. * **`DoclingServeClientBuilderFactory` is deprecated** — Use `DoclingServeApi.builder()` for the options shared by every implementation, or the new `DoclingServeClient.builder()` for client-specific settings: it returns the same builder as `DoclingServeClientBuilderFactory.newBuilder()`. The factory will be removed in a future release. From db7421dcd44f3e0761fc93ed82be30f26cae0710 Mon Sep 17 00:00:00 2001 From: Eric Deandrea Date: Thu, 22 Oct 2026 12:43:46 -0400 Subject: [PATCH 3/3] fix(api): ignore derived do_pdf_heading_hierarchy when deserializing options The flag is derived from headingHierarchyOptions and has no builder setter, so reading serialized options back would otherwise fail on the unknown property. Also fix two Javadoc links to the Lombok getters. Signed-off-by: Eric Deandrea --- .../request/options/ConvertDocumentOptions.java | 12 +++++++----- .../request/options/HeadingHierarchyOptions.java | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptions.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptions.java index 0ebbe0fb..c245cc6a 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptions.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/ConvertDocumentOptions.java @@ -6,16 +6,17 @@ import org.jspecify.annotations.Nullable; -import ai.docling.serve.api.serialization.DurationSerializationFormat; -import ai.docling.serve.api.serialization.Jackson2DurationSerializer; -import ai.docling.serve.api.serialization.Jackson3DurationSerializer; - +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import ai.docling.serve.api.serialization.DurationSerializationFormat; +import ai.docling.serve.api.serialization.Jackson2DurationSerializer; +import ai.docling.serve.api.serialization.Jackson3DurationSerializer; + /** * Options for configuring the document conversion process with Docling. */ @@ -234,7 +235,7 @@ public class ConvertDocumentOptions { private String vlmPipelineModelApi; /** - * Whether heading hierarchy inference is enabled. Derived from {@link #headingHierarchyOptions()} + * Whether heading hierarchy inference is enabled. Derived from {@link #getHeadingHierarchyOptions()} * — {@code true} when options are present, {@code false} otherwise. */ @JsonProperty("do_pdf_heading_hierarchy") @@ -252,6 +253,7 @@ public boolean doPdfHeadingHierarchy() { @Nullable private HeadingHierarchyOptions headingHierarchyOptions; + @JsonIgnoreProperties("do_pdf_heading_hierarchy") public static class Builder { } } diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptions.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptions.java index 5ab726b9..436964ea 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptions.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/options/HeadingHierarchyOptions.java @@ -57,7 +57,7 @@ public class HeadingHierarchyOptions { /** * Refine the style fallback with font weight, slant and all-caps detection. Ignored when - * {@link #useStyle()} is off. + * {@link #getUseStyle()} is off. * * @param useFontStyle true to use font style, or null for the default (true) * @return the use-font-style flag