Repository: johnzon
Updated Branches:
  refs/heads/master f4c412647 -> d8abbf0c0


JOHNZON-171 more properties handling and configurable regex impl


Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/94a2179a
Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/94a2179a
Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/94a2179a

Branch: refs/heads/master
Commit: 94a2179a3a55acd094f63dde3c6cfd4b53601003
Parents: f4c4126
Author: Romain Manni-Bucau <[email protected]>
Authored: Mon Apr 30 09:26:19 2018 +0200
Committer: Romain Manni-Bucau <[email protected]>
Committed: Mon Apr 30 09:26:19 2018 +0200

----------------------------------------------------------------------
 .../jsonschema/JsonSchemaValidatorFactory.java  | 109 +++++++++++++++++--
 .../johnzon/jsonschema/regex/JavaRegex.java     |  41 +++++++
 .../jsonschema/regex/JavascriptRegex.java       |  73 +++++++++++++
 .../jsonschema/spi/builtin/BaseValidation.java  |   3 +-
 .../spi/builtin/PatternValidation.java          |  67 +++---------
 .../jsonschema/JsonSchemaValidatorTest.java     |  38 +++++++
 6 files changed, 266 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/94a2179a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorFactory.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorFactory.java
 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorFactory.java
index 38880ba..1eb2fbb 100644
--- 
a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorFactory.java
+++ 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorFactory.java
@@ -26,13 +26,17 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
 import javax.json.JsonObject;
 import javax.json.JsonValue;
 
+import org.apache.johnzon.jsonschema.regex.JavascriptRegex;
 import org.apache.johnzon.jsonschema.spi.ValidationContext;
 import org.apache.johnzon.jsonschema.spi.ValidationExtension;
 import org.apache.johnzon.jsonschema.spi.builtin.ContainsValidation;
@@ -70,8 +74,18 @@ public class JsonSchemaValidatorFactory implements 
AutoCloseable {
 
     private final List<ValidationExtension> extensions = new ArrayList<>();
 
+    // js is closer to default and actually most used in the industry
+    private final AtomicReference<Function<String, Predicate<CharSequence>>> 
regexFactory = new AtomicReference<>(JavascriptRegex::new);
+
     public JsonSchemaValidatorFactory() {
-        extensions.addAll(asList(
+        extensions.addAll(createDefaultValidations());
+        extensions.addAll(new 
ArrayList<>(StreamSupport.stream(ServiceLoader.load(ValidationExtension.class).spliterator(),
 false)
+                .collect(toList())));
+    }
+
+    // see http://json-schema.org/latest/json-schema-validation.html
+    public List<ValidationExtension> createDefaultValidations() {
+        return asList(
                 new RequiredValidation(),
                 new TypeValidation(),
                 new EnumValidation(),
@@ -82,7 +96,7 @@ public class JsonSchemaValidatorFactory implements 
AutoCloseable {
                 new ExclusiveMinimumValidation(),
                 new MaxLengthValidation(),
                 new MinLengthValidation(),
-                new PatternValidation(),
+                new PatternValidation(regexFactory.get()),
                 new ItemsValidation(this),
                 new MaxItemsValidation(),
                 new MinItemsValidation(),
@@ -90,10 +104,9 @@ public class JsonSchemaValidatorFactory implements 
AutoCloseable {
                 new ContainsValidation(this),
                 new MaxPropertiesValidation(),
                 new MinPropertiesValidation()
-                // todo: 
http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.4 and 
following
-        ));
-        extensions.addAll(new 
ArrayList<>(StreamSupport.stream(ServiceLoader.load(ValidationExtension.class).spliterator(),
 false)
-                .collect(toList())));
+                // TODO: dependencies, propertyNames, if/then/else, 
allOf/anyOf/oneOf/not,
+                //       format validations
+        );
     }
 
     public JsonSchemaValidatorFactory appendExtensions(final 
ValidationExtension... extensions) {
@@ -106,6 +119,11 @@ public class JsonSchemaValidatorFactory implements 
AutoCloseable {
         return appendExtensions(extensions);
     }
 
+    public JsonSchemaValidatorFactory setRegexFactory(final Function<String, 
Predicate<CharSequence>> factory) {
+        regexFactory.set(factory);
+        return this;
+    }
+
     public JsonSchemaValidator newInstance(final JsonObject schema) {
         return new JsonSchemaValidator(buildValidator(ROOT_PATH, schema, 
null));
     }
@@ -119,8 +137,14 @@ public class JsonSchemaValidatorFactory implements 
AutoCloseable {
                                                                                
          final JsonObject schema,
                                                                                
          final Function<JsonValue, JsonValue> valueProvider) {
         final List<Function<JsonValue, 
Stream<ValidationResult.ValidationError>>> directValidations = 
buildDirectValidations(path, schema, valueProvider).collect(toList());
-        final Function<JsonValue, Stream<ValidationResult.ValidationError>> 
nestedValidations = buildNestedValidations(path, schema, valueProvider);
-        return new 
ValidationsFunction(Stream.concat(directValidations.stream(), 
Stream.of(nestedValidations)).collect(toList()));
+        final Function<JsonValue, Stream<ValidationResult.ValidationError>> 
nestedValidations = buildPropertiesValidations(path, schema, valueProvider);
+        final Function<JsonValue, Stream<ValidationResult.ValidationError>> 
dynamicNestedValidations = buildPatternPropertiesValidations(path, schema, 
valueProvider);
+        final Function<JsonValue, Stream<ValidationResult.ValidationError>> 
fallbackNestedValidations = buildAdditionalPropertiesValidations(path, schema, 
valueProvider);
+        return new ValidationsFunction(
+                Stream.concat(
+                        directValidations.stream(),
+                        Stream.of(nestedValidations, dynamicNestedValidations, 
fallbackNestedValidations))
+                    .collect(toList()));
     }
 
     private Stream<Function<JsonValue, 
Stream<ValidationResult.ValidationError>>> buildDirectValidations(final 
String[] path,
@@ -133,9 +157,9 @@ public class JsonSchemaValidatorFactory implements 
AutoCloseable {
                 .map(Optional::get);
     }
 
-    private Function<JsonValue, Stream<ValidationResult.ValidationError>> 
buildNestedValidations(final String[] path,
-                                                                               
                  final JsonObject schema,
-                                                                               
                  final Function<JsonValue, JsonValue> valueProvider) {
+    private Function<JsonValue, Stream<ValidationResult.ValidationError>> 
buildPropertiesValidations(final String[] path,
+                                                                               
                      final JsonObject schema,
+                                                                               
                      final Function<JsonValue, JsonValue> valueProvider) {
         return ofNullable(schema.get("properties"))
                 .filter(it -> it.getValueType() == JsonValue.ValueType.OBJECT)
                 .map(it -> it.asJsonObject().entrySet().stream()
@@ -150,6 +174,69 @@ public class JsonSchemaValidatorFactory implements 
AutoCloseable {
                 .orElse(NO_VALIDATION);
     }
 
+    // not the best impl but is it really an important case?
+    private Function<JsonValue, Stream<ValidationResult.ValidationError>> 
buildPatternPropertiesValidations(final String[] path,
+                                                                               
                      final JsonObject schema,
+                                                                               
                      final Function<JsonValue, JsonValue> valueProvider) {
+        return ofNullable(schema.get("patternProperties"))
+                .filter(it -> it.getValueType() == JsonValue.ValueType.OBJECT)
+                .map(it -> it.asJsonObject().entrySet().stream()
+                        .filter(obj -> obj.getValue().getValueType() == 
JsonValue.ValueType.OBJECT)
+                        .map(obj -> {
+                            final Predicate<CharSequence> pattern = 
regexFactory.get().apply(obj.getKey());
+                            final JsonObject currentSchema = 
obj.getValue().asJsonObject();
+                            // no cache cause otherwise it could be in 
properties
+                            return (Function<JsonValue, 
Stream<ValidationResult.ValidationError>>) validable -> {
+                                if (validable.getValueType() != 
JsonValue.ValueType.OBJECT) {
+                                    return Stream.empty();
+                                }
+                                return 
validable.asJsonObject().entrySet().stream()
+                                        .filter(e -> pattern.test(e.getKey()))
+                                        .flatMap(e -> buildValidator(
+                                                Stream.concat(Stream.of(path), 
Stream.of(e.getKey())).toArray(String[]::new),
+                                                currentSchema,
+                                                new 
ChainedValueAccessor(valueProvider, e.getKey())).apply(e.getValue()));
+                            };
+                        })
+                        .collect(toList()))
+                .map(this::toFunction)
+                .orElse(NO_VALIDATION);
+    }
+
+    private Function<JsonValue, Stream<ValidationResult.ValidationError>> 
buildAdditionalPropertiesValidations(final String[] path,
+                                                                               
                      final JsonObject schema,
+                                                                               
                      final Function<JsonValue, JsonValue> valueProvider) {
+        return ofNullable(schema.get("additionalProperties"))
+                .filter(it -> it.getValueType() == JsonValue.ValueType.OBJECT)
+                .map(it -> {
+                    Predicate<String> excluded = s -> false;
+                    if (schema.containsKey("properties")) {
+                        final Set<String> properties = 
schema.getJsonObject("properties").keySet();
+                        excluded = excluded.and(s -> !properties.contains(s));
+                    }
+                    if (schema.containsKey("patternProperties")) {
+                        final List<Predicate<CharSequence>> properties = 
schema.getJsonObject("patternProperties").keySet().stream()
+                                                                               
.map(regexFactory.get())
+                                                                               
.collect(toList());
+                        excluded = excluded.and(s -> 
properties.stream().noneMatch(p -> p.test(s)));
+                    }
+                    final Predicate<String> excludeAttrRef = excluded;
+                    final JsonObject currentSchema = it.asJsonObject();
+                    return (Function<JsonValue, 
Stream<ValidationResult.ValidationError>>) validable -> {
+                        if (validable.getValueType() != 
JsonValue.ValueType.OBJECT) {
+                            return Stream.empty();
+                        }
+                        return validable.asJsonObject().entrySet().stream()
+                                        .filter(e -> 
excludeAttrRef.test(e.getKey()))
+                                        .flatMap(e -> buildValidator(
+                                                Stream.concat(Stream.of(path), 
Stream.of(e.getKey())).toArray(String[]::new),
+                                                currentSchema,
+                                                new 
ChainedValueAccessor(valueProvider, e.getKey())).apply(e.getValue()));
+                    };
+                })
+                .orElse(NO_VALIDATION);
+    }
+
     private Function<JsonValue, Stream<ValidationResult.ValidationError>> 
toFunction(
             final List<Function<JsonValue, 
Stream<ValidationResult.ValidationError>>> validations) {
         return new ValidationsFunction(validations);

http://git-wip-us.apache.org/repos/asf/johnzon/blob/94a2179a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/regex/JavaRegex.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/regex/JavaRegex.java
 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/regex/JavaRegex.java
new file mode 100644
index 0000000..85524e4
--- /dev/null
+++ 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/regex/JavaRegex.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.johnzon.jsonschema.regex;
+
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+public class JavaRegex implements Predicate<CharSequence> {
+
+    private final Pattern pattern;
+
+    public JavaRegex(final String pattern) {
+        this.pattern = Pattern.compile(pattern);
+    }
+
+    @Override
+    public boolean test(final CharSequence charSequence) {
+        return pattern.matcher(charSequence).matches();
+    }
+
+    @Override
+    public String toString() {
+        return "JavaRegex{" + pattern + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/94a2179a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/regex/JavascriptRegex.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/regex/JavascriptRegex.java
 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/regex/JavascriptRegex.java
new file mode 100644
index 0000000..9b83389
--- /dev/null
+++ 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/regex/JavascriptRegex.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.johnzon.jsonschema.regex;
+
+import java.util.function.Predicate;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+public class JavascriptRegex implements Predicate<CharSequence> {
+
+    private static final ScriptEngine ENGINE;
+
+    static {
+        ENGINE = new ScriptEngineManager().getEngineByName("javascript");
+    }
+
+    private final String regex;
+
+    private final String indicators;
+
+    public JavascriptRegex(final String regex) {
+        if (regex.startsWith("/") && regex.length() > 1) {
+            final int end = regex.lastIndexOf('/');
+            if (end < 0) {
+                this.regex = regex;
+                this.indicators = "";
+            } else {
+                this.regex = regex.substring(1, end);
+                this.indicators = regex.substring(end + 1);
+            }
+        } else {
+            this.regex = regex;
+            this.indicators = "";
+        }
+    }
+
+    @Override
+    public boolean test(final CharSequence string) {
+        final Bindings bindings = ENGINE.createBindings();
+        bindings.put("text", string);
+        bindings.put("regex", regex);
+        bindings.put("indicators", indicators);
+        try {
+            return Boolean.class.cast(ENGINE.eval("new RegExp(regex, 
indicators).test(text)", bindings));
+        } catch (final ScriptException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "JavascriptRegex{/" + regex + "/" + indicators + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/94a2179a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/BaseValidation.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/BaseValidation.java
 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/BaseValidation.java
index 5e0b9ed..0b4e569 100644
--- 
a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/BaseValidation.java
+++ 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/BaseValidation.java
@@ -67,8 +67,9 @@ abstract class BaseValidation implements Function<JsonValue, 
Stream<ValidationRe
                 return onArray(value.asJsonArray());
             case NULL:
                 return Stream.empty();
+            default:
+                throw new IllegalArgumentException("Unsupported value type: " 
+ value);
         }
-        throw new IllegalArgumentException("Unsupported value type: " + value);
     }
 
     protected boolean isNull(final JsonValue obj) {

http://git-wip-us.apache.org/repos/asf/johnzon/blob/94a2179a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/PatternValidation.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/PatternValidation.java
 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/PatternValidation.java
index 7085225..8778444 100644
--- 
a/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/PatternValidation.java
+++ 
b/johnzon-jsonschema/src/main/java/org/apache/johnzon/jsonschema/spi/builtin/PatternValidation.java
@@ -25,38 +25,41 @@ import java.util.stream.Stream;
 
 import javax.json.JsonString;
 import javax.json.JsonValue;
-import javax.script.Bindings;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
 
 import org.apache.johnzon.jsonschema.ValidationResult;
 import org.apache.johnzon.jsonschema.spi.ValidationContext;
 import org.apache.johnzon.jsonschema.spi.ValidationExtension;
 
 public class PatternValidation implements ValidationExtension {
+    private final Function<String, Predicate<CharSequence>> predicateFactory;
+
+    public PatternValidation(final Function<String, Predicate<CharSequence>> 
predicateFactory) {
+        this.predicateFactory = predicateFactory;
+    }
+
     @Override
     public Optional<Function<JsonValue, 
Stream<ValidationResult.ValidationError>>> create(final ValidationContext 
model) {
         if (model.getSchema().getString("type", "object").equals("string")) {
             return Optional.ofNullable(model.getSchema().get("pattern"))
                     .filter(val -> val.getValueType() == 
JsonValue.ValueType.STRING)
-                    .map(pattern -> new Impl(model.toPointer(), 
model.getValueProvider(), JsonString.class.cast(pattern).getString()));
+                    .map(pattern -> new Impl(model.toPointer(), 
model.getValueProvider(), 
predicateFactory.apply(JsonString.class.cast(pattern).getString())));
         }
         return Optional.empty();
     }
 
     private static class Impl extends BaseValidation {
-        private final JsRegex jsRegex;
+        private final Predicate<CharSequence> matcher;
 
-        private Impl(final String pointer, final Function<JsonValue, 
JsonValue> valueProvider, final String pattern) {
+        private Impl(final String pointer, final Function<JsonValue, 
JsonValue> valueProvider,
+                     final Predicate<CharSequence> matcher) {
             super(pointer, valueProvider, JsonValue.ValueType.STRING);
-            this.jsRegex = new JsRegex(pattern);
+            this.matcher = matcher;
         }
 
         @Override
         public Stream<ValidationResult.ValidationError> onString(final 
JsonString value) {
-            if (!jsRegex.test(value.getString())) {
-                return Stream.of(new ValidationResult.ValidationError(pointer, 
value + " doesn't match " + jsRegex));
+            if (!matcher.test(value.getString())) {
+                return Stream.of(new ValidationResult.ValidationError(pointer, 
value + " doesn't match " + matcher));
             }
             return Stream.empty();
         }
@@ -64,51 +67,9 @@ public class PatternValidation implements 
ValidationExtension {
         @Override
         public String toString() {
             return "Pattern{" +
-                    "regex=" + jsRegex +
+                    "regex=" + matcher +
                     ", pointer='" + pointer + '\'' +
                     '}';
         }
     }
-
-    private static class JsRegex implements Predicate<CharSequence> {
-
-        private static final ScriptEngine ENGINE;
-
-        static {
-            ENGINE = new ScriptEngineManager().getEngineByName("javascript");
-        }
-
-        private final String regex;
-
-        private final String indicators;
-
-        private JsRegex(final String regex) {
-            if (regex.startsWith("/") && regex.length() > 1) {
-                final int end = regex.lastIndexOf('/');
-                if (end < 0) {
-                    this.regex = regex;
-                    this.indicators = "";
-                } else {
-                    this.regex = regex.substring(1, end);
-                    this.indicators = regex.substring(end + 1);
-                }
-            } else {
-                this.regex = regex;
-                this.indicators = "";
-            }
-        }
-
-        @Override
-        public boolean test(final CharSequence string) {
-            final Bindings bindings = ENGINE.createBindings();
-            bindings.put("text", string);
-            bindings.put("regex", regex);
-            bindings.put("indicators", indicators);
-            try {
-                return Boolean.class.cast(ENGINE.eval("new RegExp(regex, 
indicators).test(text)", bindings));
-            } catch (final ScriptException e) {
-                return false;
-            }
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/94a2179a/johnzon-jsonschema/src/test/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonschema/src/test/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorTest.java
 
b/johnzon-jsonschema/src/test/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorTest.java
index bde29c9..ff101c6 100644
--- 
a/johnzon-jsonschema/src/test/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorTest.java
+++ 
b/johnzon-jsonschema/src/test/java/org/apache/johnzon/jsonschema/JsonSchemaValidatorTest.java
@@ -555,4 +555,42 @@ public class JsonSchemaValidatorTest {
 
         validator.close();
     }
+
+    @Test
+    public void patternProperties() {
+        final JsonSchemaValidator validator = 
factory.newInstance(jsonFactory.createObjectBuilder()
+                .add("type", "object")
+                .add("patternProperties", jsonFactory.createObjectBuilder()
+                        .add("[0-9]+", 
jsonFactory.createObjectBuilder().add("type", "number"))
+                    .build())
+                .build());
+
+        
assertTrue(validator.apply(jsonFactory.createObjectBuilder().build()).isSuccess());
+        assertTrue(validator.apply(jsonFactory.createObjectBuilder()
+                .add("1", 1)
+                .build()).isSuccess());
+        assertTrue(validator.apply(jsonFactory.createObjectBuilder()
+                .add("1", "test")
+                .build()).isSuccess());
+
+        validator.close();
+    }
+
+    @Test
+    public void additionalProperties() {
+        final JsonSchemaValidator validator = 
factory.newInstance(jsonFactory.createObjectBuilder()
+                .add("type", "object")
+                .add("additionalProperties", 
jsonFactory.createObjectBuilder().add("type", "number"))
+                .build());
+
+        
assertTrue(validator.apply(jsonFactory.createObjectBuilder().build()).isSuccess());
+        assertTrue(validator.apply(jsonFactory.createObjectBuilder()
+                .add("1", 1)
+                .build()).isSuccess());
+        assertTrue(validator.apply(jsonFactory.createObjectBuilder()
+                .add("1", "test")
+                .build()).isSuccess());
+
+        validator.close();
+    }
 }

Reply via email to