Repository: victools/jsonschema-generator
Pull request #194 (2021-09-02 20:02:37)

Add support for readOnly and writeOnly keywords
- support `readOnly` and `writeOnly` in main `jsonschema-generator`
- implement configuration for `readOnly` and `writeOnly` in `jsonschema-module-swagger-2` based on `@Schema.accessMode` as requested in issue #193


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 79e6e46..8c7f6a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,10 +5,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
+### `jsonschema-generator`
+#### Added
+- Support `readOnly` and `writeOnly` keywords
+
 ### `jsonschema-module-jackson`
 #### Changed
 - subtype resolution now also respects `@JsonTypeInfo` annotation on common interface (and not just common super class)
 
+### `jsonschema-module-swagger-2`
+#### Added
+- Mark a subschema as `readOnly` or `writeOnly` based on a field or method's `@Schema.accessMode`
+
 ## [4.18.0] - 2021-03-21
 ### `jsonschema-generator`
 #### Changed
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
index 5860c47..2234c18 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
@@ -258,6 +258,38 @@ public interface SchemaGeneratorConfig {
      */
     boolean isRequired(MethodScope method);
 
+    /**
+     * Check whether a field/property value is deemed read-only, i.e., may be ignored or rejected when included in a request.
+     *
+     * @param field object's field/property to check
+     * @return whether the field/property value should be read-only
+     */
+    boolean isReadOnly(FieldScope field);
+
+    /**
+     * Check whether a method value is deemed read-only, i.e., may be ignored or rejected when included in a request.
+     *
+     * @param method method to check
+     * @return whether the method value should be read-only
+     */
+    boolean isReadOnly(MethodScope method);
+
+    /**
+     * Check whether a field/property value is deemed write-only, i.e., is not being returned in responses.
+     *
+     * @param field object's field/property to check
+     * @return whether the field/property value should be write-only
+     */
+    boolean isWriteOnly(FieldScope field);
+
+    /**
+     * Check whether a method value is deemed write-only, i.e., is not being returned in responses.
+     *
+     * @param method method to check
+     * @return whether the method value should be write-only
+     */
+    boolean isWriteOnly(MethodScope method);
+
     /**
      * Check whether a field/property should be ignored.
      *
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPart.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPart.java
index 94d98a9..e137775 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPart.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigPart.java
@@ -46,6 +46,8 @@ public class SchemaGeneratorConfigPart<M extends MemberScope<?, ?>> extends Sche
      */
     private final List<Predicate<M>> ignoreChecks = new ArrayList<>();
     private final List<Predicate<M>> requiredChecks = new ArrayList<>();
+    private final List<Predicate<M>> readOnlyChecks = new ArrayList<>();
+    private final List<Predicate<M>> writeOnlyChecks = new ArrayList<>();
     private final List<ConfigFunction<M, Boolean>> nullableChecks = new ArrayList<>();
 
     /*
@@ -150,6 +152,48 @@ public class SchemaGeneratorConfigPart<M extends MemberScope<?, ?>> extends Sche
         return this.requiredChecks.stream().anyMatch(check -> check.test(member));
     }
 
+    /**
+     * Setter for read-only check.
+     *
+     * @param check how to determine whether a given reference should be deemed read-only
+     * @return this config part (for chaining)
+     */
+    public SchemaGeneratorConfigPart<M> withReadOnlyCheck(Predicate<M> check) {
+        this.readOnlyChecks.add(check);
+        return this;
+    }
+
+    /**
+     * Determine whether a given member should be deemed read-only in its declaring type.
+     *
+     * @param member member to check
+     * @return whether the member is read-only (defaults to false)
+     */
+    public boolean isReadOnly(M member) {
+        return this.readOnlyChecks.stream().anyMatch(check -> check.test(member));
+    }
+
+    /**
+     * Setter for write-only check.
+     *
+     * @param check how to determine whether a given reference should be deemed write-only
+     * @return this config part (for chaining)
+     */
+    public SchemaGeneratorConfigPart<M> withWriteOnlyCheck(Predicate<M> check) {
+        this.writeOnlyChecks.add(check);
+        return this;
+    }
+
+    /**
+     * Determine whether a given member should be deemed write-only in its declaring type.
+     *
+     * @param member member to check
+     * @return whether the member is write-only (defaults to false)
+     */
+    public boolean isWriteOnly(M member) {
+        return this.writeOnlyChecks.stream().anyMatch(check -> check.test(member));
+    }
+
     /**
      * Setter for nullable check.
      *
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaKeyword.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaKeyword.java
index b413262..9fb8437 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaKeyword.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaKeyword.java
@@ -70,6 +70,14 @@ public enum SchemaKeyword {
     TAG_CONST("const"),
     TAG_ENUM("enum"),
     TAG_DEFAULT("default"),
+    /**
+     * Beware that this keyword was only introduced in {@link SchemaVersion#DRAFT_7}.
+     */
+    TAG_READ_ONLY("readOnly"),
+    /**
+     * Beware that this keyword was only introduced in {@link SchemaVersion#DRAFT_7}.
+     */
+    TAG_WRITE_ONLY("writeOnly"),
 
     TAG_LENGTH_MIN("minLength"),
     TAG_LENGTH_MAX("maxLength"),
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/AttributeCollector.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/AttributeCollector.java
index 9f04e11..253f2b3 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/AttributeCollector.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/AttributeCollector.java
@@ -74,6 +74,8 @@ public class AttributeCollector {
         collector.setDescription(node, config.resolveDescription(field), generationContext);
         collector.setDefault(node, config.resolveDefault(field), generationContext);
         collector.setEnum(node, config.resolveEnum(field), generationContext);
+        collector.setReadOnly(node, config.isReadOnly(field), generationContext);
+        collector.setWriteOnly(node, config.isWriteOnly(field), generationContext);
         collector.setAdditionalProperties(node, config.resolveAdditionalProperties(field), generationContext);
         collector.setPatternProperties(node, config.resolvePatternProperties(field), generationContext);
         collector.setStringMinLength(node, config.resolveStringMinLength(field), generationContext);
@@ -108,6 +110,8 @@ public class AttributeCollector {
         collector.setDescription(node, config.resolveDescription(method), generationContext);
         collector.setDefault(node, config.resolveDefault(method), generationContext);
         collector.setEnum(node, config.resolveEnum(method), generationContext);
+        collector.setReadOnly(node, config.isReadOnly(method), generationContext);
+        collector.setWriteOnly(node, config.isWriteOnly(method), generationContext);
         collector.setAdditionalProperties(node, config.resolveAdditionalProperties(method), generationContext);
         collector.setPatternProperties(node, config.resolvePatternProperties(method), generationContext);
         collector.setStringMinLength(node, config.resolveStringMinLength(method), generationContext);
@@ -458,6 +462,36 @@ public class AttributeCollector {
         }
     }
 
+    /**
+     * Setter for "{@link SchemaKeyword#TAG_READ_ONLY}" attribute.
+     *
+     * @param node schema node to set attribute on
+     * @param readOnly attribute value to set
+     * @param generationContext generation context, including configuration to apply when looking-up attribute values
+     * @return this instance (for chaining)
+     */
+    public AttributeCollector setReadOnly(ObjectNode node, boolean readOnly, SchemaGenerationContext generationContext) {
+        if (readOnly) {
+            node.put(generationContext.getKeyword(SchemaKeyword.TAG_READ_ONLY), readOnly);
+        }
+        return this;
+    }
+
+    /**
+     * Setter for "{@link SchemaKeyword#TAG_WRITE_ONLY}" attribute.
+     *
+     * @param node schema node to set attribute on
+     * @param writeOnly attribute value to set
+     * @param generationContext generation context, including configuration to apply when looking-up attribute values
+     * @return this instance (for chaining)
+     */
+    public AttributeCollector setWriteOnly(ObjectNode node, boolean writeOnly, SchemaGenerationContext generationContext) {
+        if (writeOnly) {
+            node.put(generationContext.getKeyword(SchemaKeyword.TAG_WRITE_ONLY), writeOnly);
+        }
+        return this;
+    }
+
     /**
      * Setter for "{@link SchemaKeyword#TAG_ADDITIONAL_PROPERTIES}" attribute.
      *
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
index abec3e3..bb1bdef 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
@@ -302,6 +302,26 @@ public class SchemaGeneratorConfigImpl implements SchemaGeneratorConfig {
         return this.methodConfigPart.isRequired(method);
     }
 
+    @Override
+    public boolean isReadOnly(FieldScope field) {
+        return this.fieldConfigPart.isReadOnly(field);
+    }
+
+    @Override
+    public boolean isReadOnly(MethodScope method) {
+        return this.methodConfigPart.isReadOnly(method);
+    }
+
+    @Override
+    public boolean isWriteOnly(FieldScope field) {
+        return this.fieldConfigPart.isWriteOnly(field);
+    }
+
+    @Override
+    public boolean isWriteOnly(MethodScope method) {
+        return this.methodConfigPart.isWriteOnly(method);
+    }
+
     @Override
     public List<ResolvedType> resolveTargetTypeOverrides(FieldScope field) {
         return this.fieldConfigPart.resolveTargetTypeOverrides(field);
diff --git a/jsonschema-module-swagger-2/README.md b/jsonschema-module-swagger-2/README.md
index e77f984..e8e8125 100644
--- a/jsonschema-module-swagger-2/README.md
+++ b/jsonschema-module-swagger-2/README.md
@@ -24,16 +24,18 @@ Module for the [jsonschema-generator](../jsonschema-generator) – deriving JSON
 18. From `@Schema(nullable = true)` on fields/methods, include `null` in its `"type"`.
 19. From `@Schema(allowableValues = …)` on fields/methods, derive its `"const"`/`"enum"`.
 20. From `@Schema(defaultValue = …)` on fields/methods, derive its `"default"`.
-21. From `@Schema(minLength = …)` on fields/methods, derive its `"minLength"`.
-22. From `@Schema(maxLength = …)` on fields/methods, derive its `"maxLength"`.
-23. From `@Schema(format = …)` on fields/methods, derive its `"format"`.
-24. From `@Schema(pattern = …)` on fields/methods, derive its `"pattern"`.
-25. From `@Schema(multipleOf = …)` on fields/methods, derive its `"multipleOf"`.
-26. From `@Schema(minimum = …, exclusiveMinimum = …)` on fields/methods, derive its `"minimum"`/`"exclusiveMinimum"`.
-27. From `@Schema(maximum = …, exclusiveMaximum = …)` on fields/methods, derive its `"maximum"`/`"exclusiveMaximum"`.
-28. From `@ArraySchema(minItems = …)` on fields/methods, derive its `"minItems"`.
-29. From `@ArraySchema(maxItems = …)` on fields/methods, derive its `"maxItems"`.
-30. From `@ArraySchema(uniqueItems = …)` on fields/methods, derive its `"uniqueItems"`.
+21. From `@Schema(accessMode = AccessMode.READ_ONLY)` on fields/methods, to mark them as `"readOnly"`.
+22. From `@Schema(accessMode = AccessMode.WRITE_ONLY)` on fields/methods, to mark them as `"writeOnly"`.
+23. From `@Schema(minLength = …)` on fields/methods, derive its `"minLength"`.
+24. From `@Schema(maxLength = …)` on fields/methods, derive its `"maxLength"`.
+25. From `@Schema(format = …)` on fields/methods, derive its `"format"`.
+26. From `@Schema(pattern = …)` on fields/methods, derive its `"pattern"`.
+27. From `@Schema(multipleOf = …)` on fields/methods, derive its `"multipleOf"`.
+28. From `@Schema(minimum = …, exclusiveMinimum = …)` on fields/methods, derive its `"minimum"`/`"exclusiveMinimum"`.
+29. From `@Schema(maximum = …, exclusiveMaximum = …)` on fields/methods, derive its `"maximum"`/`"exclusiveMaximum"`.
+30. From `@ArraySchema(minItems = …)` on fields/methods, derive its `"minItems"`.
+31. From `@ArraySchema(maxItems = …)` on fields/methods, derive its `"maxItems"`.
+32. From `@ArraySchema(uniqueItems = …)` on fields/methods, derive its `"uniqueItems"`.
 
 Schema attributes derived from `@Schema` on fields are also applied to their respective getter methods.
 Schema attributes derived from `@Schema` on getter methods are also applied to their associated fields.
diff --git a/jsonschema-module-swagger-2/src/main/java/com/github/victools/jsonschema/module/swagger2/Swagger2Module.java b/jsonschema-module-swagger-2/src/main/java/com/github/victools/jsonschema/module/swagger2/Swagger2Module.java
index 8585f20..f40b022 100644
--- a/jsonschema-module-swagger-2/src/main/java/com/github/victools/jsonschema/module/swagger2/Swagger2Module.java
+++ b/jsonschema-module-swagger-2/src/main/java/com/github/victools/jsonschema/module/swagger2/Swagger2Module.java
@@ -75,6 +75,8 @@ public class Swagger2Module implements Module {
         configPart.withTitleResolver(this::resolveTitle);
         configPart.withRequiredCheck(this::checkRequired);
         configPart.withNullableCheck(this::checkNullable);
+        configPart.withReadOnlyCheck(this::checkReadOnly);
+        configPart.withWriteOnlyCheck(this::checkWriteOnly);
         configPart.withEnumResolver(this::resolveEnum);
         configPart.withDefaultResolver(this::resolveDefault);
 
@@ -176,6 +178,28 @@ public class Swagger2Module implements Module {
                 .isPresent();
     }
 
+    /**
+     * Determine whether the given field/method is deemed read-only based on {@code @Schema(accessMode = AccessMode.READ_ONLY)}.
+     *
+     * @param member field/method to check
+     * @return whether the field/method is read-only
+     */
+    protected boolean checkReadOnly(MemberScope<?, ?> member) {
+        return this.getSchemaAnnotationValue(member, Schema::accessMode, Schema.AccessMode.READ_ONLY::equals)
+                .isPresent();
+    }
+
+    /**
+     * Determine whether the given field/method is deemed write-only based on {@code @Schema(accessMode = AccessMode.WRITE_ONLY)}.
+     *
+     * @param member field/method to check
+     * @return whether the field/method is write-only
+     */
+    protected boolean checkWriteOnly(MemberScope<?, ?> member) {
+        return this.getSchemaAnnotationValue(member, Schema::accessMode, Schema.AccessMode.WRITE_ONLY::equals)
+                .isPresent();
+    }
+
     /**
      * Look-up the finite list of possible values from {@code @Schema(allowableValues = ...)}.
      *
diff --git a/slate-docs/source/includes/_main-generator.md b/slate-docs/source/includes/_main-generator.md
index 0e2b783..ee2f40b 100644
--- a/slate-docs/source/includes/_main-generator.md
+++ b/slate-docs/source/includes/_main-generator.md
@@ -535,6 +535,26 @@ configBuilder.forMethods()
 
 `withRequiredCheck()` is expecting the indication to be returned whether a given `FieldScope`/`MethodScope` should be included in the `"required"` attribute – if any check returns `true`, the field/method will be deemed `"required"`.
 
+## `"readOnly"` Keyword
+```java
+configBuilder.forFields()
+    .withReadOnlyCheck(field -> field.getAnnotationConsideringFieldAndGetter(ReadOnly.class) != null);
+configBuilder.forMethods()
+    .withReadOnlyCheck(method -> method.getAnnotationConsideringFieldAndGetter(ReadOnly.class) != null);
+```
+
+`withReadOnlyCheck()` is expecting the indication to be returned whether a given `FieldScope`/`MethodScope` should be included in the `"readOnly"` attribute – if any check returns `true`, the field/method will be deemed `"readOnly"`.
+
+## `"writeOnly"` Keyword
+```java
+configBuilder.forFields()
+    .withRequiredCheck(field -> field.getAnnotationConsideringFieldAndGetter(WriteOnly.class) != null);
+configBuilder.forMethods()
+    .withRequiredCheck(method -> method.getAnnotationConsideringFieldAndGetter(WriteOnly.class) != null);
+```
+
+`withWriteOnlyCheck()` is expecting the indication to be returned whether a given `FieldScope`/`MethodScope` should be included in the `"writeOnly"` attribute – if any check returns `true`, the field/method will be deemed `"writeOnly"`.
+
 ## `"title"` Keyword
 ```java
 configBuilder.forTypesInGeneral()
diff --git a/slate-docs/source/includes/_swagger-2-module.md b/slate-docs/source/includes/_swagger-2-module.md
index 3651eff..6f0f346 100644
--- a/slate-docs/source/includes/_swagger-2-module.md
+++ b/slate-docs/source/includes/_swagger-2-module.md
@@ -32,16 +32,18 @@ SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(Sc
 18. From `@Schema(nullable = true)` on fields/methods, include `null` in its `"type"`.
 19. From `@Schema(allowableValues = …)` on fields/methods, derive its `"const"`/`"enum"`.
 20. From `@Schema(defaultValue = …)` on fields/methods, derive its `"default"`.
-21. From `@Schema(minLength = …)` on fields/methods, derive its `"minLength"`.
-22. From `@Schema(maxLength = …)` on fields/methods, derive its `"maxLength"`.
-23. From `@Schema(format = …)` on fields/methods, derive its `"format"`.
-24. From `@Schema(pattern = …)` on fields/methods, derive its `"pattern"`.
-25. From `@Schema(multipleOf = …)` on fields/methods, derive its `"multipleOf"`.
-26. From `@Schema(minimum = …, exclusiveMinimum = …)` on fields/methods, derive its `"minimum"`/`"exclusiveMinimum"`.
-27. From `@Schema(maximum = …, exclusiveMaximum = …)` on fields/methods, derive its `"maximum"`/`"exclusiveMaximum"`.
-28. From `@ArraySchema(minItems = …)` on fields/methods, derive its `"minItems"`.
-29. From `@ArraySchema(maxItems = …)` on fields/methods, derive its `"maxItems"`.
-30. From `@ArraySchema(uniqueItems = …)` on fields/methods, derive its `"uniqueItems"`.
+21. From `@Schema(accessMode = AccessMode.READ_ONLY)` on fields/methods, to mark them as `"readOnly"`.
+22. From `@Schema(accessMode = AccessMode.WRITE_ONLY)` on fields/methods, to mark them as `"writeOnly"`.
+23. From `@Schema(minLength = …)` on fields/methods, derive its `"minLength"`.
+24. From `@Schema(maxLength = …)` on fields/methods, derive its `"maxLength"`.
+25. From `@Schema(format = …)` on fields/methods, derive its `"format"`.
+26. From `@Schema(pattern = …)` on fields/methods, derive its `"pattern"`.
+27. From `@Schema(multipleOf = …)` on fields/methods, derive its `"multipleOf"`.
+28. From `@Schema(minimum = …, exclusiveMinimum = …)` on fields/methods, derive its `"minimum"`/`"exclusiveMinimum"`.
+29. From `@Schema(maximum = …, exclusiveMaximum = …)` on fields/methods, derive its `"maximum"`/`"exclusiveMaximum"`.
+30. From `@ArraySchema(minItems = …)` on fields/methods, derive its `"minItems"`.
+31. From `@ArraySchema(maxItems = …)` on fields/methods, derive its `"maxItems"`.
+32. From `@ArraySchema(uniqueItems = …)` on fields/methods, derive its `"uniqueItems"`.
 
 Schema attributes derived from `@Schema`/`@ArraySchema` on fields are also applied to their respective getter methods.
 Schema attributes derived from `@Schema`/`@ArraySchema` on getter methods are also applied to their associated fields.


Test patch:
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorComplexTypesTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorComplexTypesTest.java
index 1906974..ff1bc3f 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorComplexTypesTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorComplexTypesTest.java
@@ -93,7 +93,9 @@ public class SchemaGeneratorComplexTypesTest {
         populateTypeConfigPart(configPart, descriptionPrefix);
         configPart
                 .withNullableCheck(member -> !member.getName().startsWith("nested"))
-                .withRequiredCheck(member -> member.getName().startsWith("nested"));
+                .withRequiredCheck(member -> member.getName().startsWith("nested"))
+                .withReadOnlyCheck(member -> member.isFinal())
+                .withWriteOnlyCheck(member -> member.getType() != null && TestClass4.class.isAssignableFrom(member.getType().getErasedType()));
     }
 
     Object parametersForTestGenerateSchema() {
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-JAVA_OBJECT-methodattributes.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-JAVA_OBJECT-methodattributes.json
index e39825a..af873be 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-JAVA_OBJECT-methodattributes.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-JAVA_OBJECT-methodattributes.json
@@ -13,6 +13,7 @@
                     "title": "String",
                     "description": "looked-up from method: String",
                     "const": "constant string value",
+                    "readOnly": true,
                     "minLength": 1,
                     "maxLength": 256,
                     "format": "date",
@@ -223,6 +224,7 @@
             },
             "title": "TestClass4<Integer, String>",
             "description": "looked-up from method: TestClass4<Integer, String>",
+            "writeOnly": true,
             "additionalProperties": {
                 "type": "string"
             }
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-PLAIN_JSON-fieldattributes.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-PLAIN_JSON-fieldattributes.json
index a761e39..292f5fd 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-PLAIN_JSON-fieldattributes.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-PLAIN_JSON-fieldattributes.json
@@ -153,6 +153,7 @@
             },
             "title": "TestClass4<Integer, String>",
             "description": "looked-up from field: TestClass4<Integer, String>",
+            "writeOnly": true,
             "additionalProperties": {
                 "type": "string"
             }
diff --git a/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/IntegrationTest.java b/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/IntegrationTest.java
index 0c5427b..cb7cb1c 100644
--- a/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/IntegrationTest.java
+++ b/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/IntegrationTest.java
@@ -137,10 +137,10 @@ public class IntegrationTest {
 
     static class Foo {
 
-        @Schema(implementation = PersonReference.class)
+        @Schema(implementation = PersonReference.class, accessMode = Schema.AccessMode.WRITE_ONLY)
         private Reference<Person> person;
 
-        @Schema(ref = "http://example.com/bar")
+        @Schema(ref = "http://example.com/bar", accessMode = Schema.AccessMode.READ_ONLY)
         private Object bar;
     }
 }
diff --git a/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/Swagger2ModuleTest.java b/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/Swagger2ModuleTest.java
index a01bab7..7f836f4 100644
--- a/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/Swagger2ModuleTest.java
+++ b/jsonschema-module-swagger-2/src/test/java/com/github/victools/jsonschema/module/swagger2/Swagger2ModuleTest.java
@@ -82,6 +82,8 @@ public class Swagger2ModuleTest {
         Mockito.verify(configPart).withTitleResolver(Mockito.any());
         Mockito.verify(configPart).withRequiredCheck(Mockito.any());
         Mockito.verify(configPart).withNullableCheck(Mockito.any());
+        Mockito.verify(configPart).withReadOnlyCheck(Mockito.any());
+        Mockito.verify(configPart).withWriteOnlyCheck(Mockito.any());
         Mockito.verify(configPart).withEnumResolver(Mockito.any());
         Mockito.verify(configPart).withDefaultResolver(Mockito.any());
 
diff --git a/jsonschema-module-swagger-2/src/test/resources/com/github/victools/jsonschema/module/swagger2/integration-test-result-Foo.json b/jsonschema-module-swagger-2/src/test/resources/com/github/victools/jsonschema/module/swagger2/integration-test-result-Foo.json
index ae305a9..e332b73 100644
--- a/jsonschema-module-swagger-2/src/test/resources/com/github/victools/jsonschema/module/swagger2/integration-test-result-Foo.json
+++ b/jsonschema-module-swagger-2/src/test/resources/com/github/victools/jsonschema/module/swagger2/integration-test-result-Foo.json
@@ -16,10 +16,12 @@
     "type": "object",
     "properties": {
         "bar": {
-            "$ref": "http://example.com/bar"
+            "$ref": "http://example.com/bar",
+            "readOnly": true
         },
         "person": {
-            "$ref": "#/$defs/referenceToPerson"
+            "$ref": "#/$defs/referenceToPerson",
+            "writeOnly": true
         }
     }
 }