` enables a few features:
-
-- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)
-- Lazily [validating the API response against the expected shape](#response-validation)
-- Representing absent vs explicitly null values
-
-### Why don't you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?
-
-It is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don't want to introduce a breaking change every time we add a field to a class.
-
-### Why don't you use checked exceptions?
-
-Checked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.
-
-Checked exceptions:
-
-- Are verbose to handle
-- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error
-- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)
-- Don't play well with lambdas (also due to the function coloring problem)
+## Requirements
-## Semantic versioning
+Java 8+
-This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
+## Contributing
-1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
-2. Changes that we do not expect to impact the vast majority of users in practice.
+See [CONTRIBUTING.md](./CONTRIBUTING.md).
-We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
+## License
-We are keen for your feedback; please open an [issue](https://www.github.com/anthropics/anthropic-sdk-java/issues) with questions, bugs, or suggestions.
+This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/core/Properties.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/core/Properties.kt
index ef284963..97275547 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/core/Properties.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/core/Properties.kt
@@ -34,9 +34,9 @@ fun getOsName(): String {
}
}
-fun getOsVersion(): String = System.getProperty("os.version", "unknown")
+fun getOsVersion(): String = System.getProperty("os.version", "unknown") ?: "unknown"
fun getPackageVersion(): String =
- AnthropicClient::class.java.`package`.implementationVersion ?: "unknown"
+ AnthropicClient::class.java.`package`?.implementationVersion ?: "unknown"
-fun getJavaVersion(): String = System.getProperty("java.version", "unknown")
+fun getJavaVersion(): String = System.getProperty("java.version", "unknown") ?: "unknown"
diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsExample.java
index 95853818..31a5e682 100644
--- a/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsExample.java
+++ b/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsExample.java
@@ -3,6 +3,7 @@
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.MessageCreateParams;
+import com.anthropic.models.messages.Model;
import com.anthropic.models.messages.StructuredMessageCreateParams;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
@@ -10,10 +11,18 @@
import java.util.List;
/**
+ *
* Example demonstrating GA (non-beta) structured outputs.
- *
- *
This example uses the GA Messages API with structured outputs, which does NOT require any beta
+ *
+ *
+ * This example derives the JSON schema for the output format from the structure of Java classes.
+ * Compare to {@link StructuredOutputsRawExample} where the low-level API is used to define the same
+ * JSON schema without using Java classes.
+ *
+ *
+ * This example uses the GA Messages API with structured outputs, which does NOT require any beta
* headers. Compare with {@link BetaStructuredOutputsExample} which uses the beta API.
+ *
*/
public final class StructuredOutputsExample {
@@ -65,7 +74,7 @@ public static void main(String[] args) {
// GA structured outputs - no beta header required!
// Use client.messages() instead of client.beta().messages()
StructuredMessageCreateParams createParams = MessageCreateParams.builder()
- .model("claude-sonnet-4-5")
+ .model(Model.CLAUDE_SONNET_4_5_20250929)
.maxTokens(2048)
.outputConfig(BookList.class)
.addUserMessage("List some famous late twentieth century novels.")
diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsRawExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsRawExample.java
new file mode 100644
index 00000000..2b51a810
--- /dev/null
+++ b/anthropic-java-example/src/main/java/com/anthropic/example/StructuredOutputsRawExample.java
@@ -0,0 +1,108 @@
+package com.anthropic.example;
+
+import com.anthropic.client.AnthropicClient;
+import com.anthropic.client.okhttp.AnthropicOkHttpClient;
+import com.anthropic.core.JsonValue;
+import com.anthropic.models.messages.JsonOutputFormat;
+import com.anthropic.models.messages.MessageCreateParams;
+import com.anthropic.models.messages.Model;
+import com.anthropic.models.messages.OutputConfig;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An example of structured outputs using the low-level ("raw") API to define the JSON schema for
+ * the output format. Compare to {@link StructuredOutputsExample} where the same JSON schema is
+ * derived from the structure of Java classes.
+ */
+public final class StructuredOutputsRawExample {
+
+ private StructuredOutputsRawExample() {}
+
+ public static void main(String[] args) {
+ // Configure by setting the `ANTHROPIC_API_KEY` environment variable.
+ AnthropicClient client = AnthropicOkHttpClient.fromEnv();
+
+ JsonOutputFormat.Schema schema = JsonOutputFormat.Schema.builder()
+ // The "$schema" property can be omitted.
+ .putAdditionalProperty("type", JsonValue.from("object"))
+ .putAdditionalProperty(
+ "properties",
+ JsonValue.from(Map.of(
+ "books",
+ Map.of(
+ "minItems",
+ 1,
+ "type",
+ "array",
+ "items",
+ Map.of(
+ "type",
+ "object",
+ "properties",
+ Map.of(
+ "author",
+ Map.of(
+ "type",
+ "object",
+ "properties",
+ Map.of(
+ "birthYear", Map.of("type", "integer"),
+ "deathYear",
+ Map.of(
+ "type",
+ "string",
+ "description",
+ "The year the person"
+ + " died, or"
+ + " 'present' if"
+ + " the person is"
+ + " living."),
+ "name",
+ Map.of(
+ "type",
+ "string",
+ "description",
+ "The first"
+ + " name"
+ + " and surname"
+ + " of the"
+ + " person.")),
+ "required",
+ List.of("birthYear", "deathYear", "name"),
+ "additionalProperties",
+ false),
+ "genre", Map.of("type", "string"),
+ "publicationYear",
+ Map.of(
+ "type",
+ "integer",
+ "description",
+ "The year in which the book was first"
+ + " published. No earlier than"
+ + " 1500."),
+ "title", Map.of("type", "string")),
+ "required",
+ List.of("author", "genre", "publicationYear", "title"),
+ "additionalProperties",
+ false)))))
+ .putAdditionalProperty("required", JsonValue.from(List.of("books")))
+ .putAdditionalProperty("additionalProperties", JsonValue.from(false))
+ .build();
+
+ OutputConfig outputConfig = OutputConfig.builder()
+ .format(JsonOutputFormat.builder().schema(schema).build())
+ .build();
+
+ MessageCreateParams createParams = MessageCreateParams.builder()
+ .model(Model.CLAUDE_SONNET_4_5_20250929)
+ .maxTokens(2048)
+ .outputConfig(outputConfig)
+ .addUserMessage("List some famous late twentieth century novels.")
+ .build();
+
+ client.messages().create(createParams).content().stream()
+ .flatMap(contentBlock -> contentBlock.text().stream())
+ .forEach(textBlock -> System.out.println("JSON output: " + textBlock.text()));
+ }
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index bf7d432d..b6645293 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -8,7 +8,7 @@ repositories {
allprojects {
group = "com.anthropic"
- version = "2.15.0" // x-release-please-version
+ version = "2.16.0" // x-release-please-version
}
subprojects {