[JOHNZON-339] johnzon.rejectDuplicateKeys support
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java b/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java
index ded93e3..c851717 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java
@@ -32,11 +32,11 @@
protected final Map<String, Object> internalConfig = new HashMap<String, Object>();
- protected AbstractJsonFactory(final Map<String, ?> config, Collection<String> supportedConfigKeys, Collection<String> defaultSupportedConfigKeys) {
- if(config != null && config.size() > 0) {
-
+ protected AbstractJsonFactory(final Map<String, ?> config, Collection<String> supportedConfigKeys,
+ final Collection<String> defaultSupportedConfigKeys) {
+ if(config != null && !config.isEmpty()) {
if(defaultSupportedConfigKeys != null) {
- supportedConfigKeys = new ArrayList<String>(supportedConfigKeys);
+ supportedConfigKeys = new ArrayList<>(supportedConfigKeys);
supportedConfigKeys.addAll(defaultSupportedConfigKeys);
}
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java
index cf64a36..6edde73 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java
@@ -59,7 +59,7 @@
throw new IllegalStateException(current + " doesn't support getObject()");
}
- JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider());
+ JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT);
return jsonReader.readObject();
}
@@ -71,7 +71,7 @@
throw new IllegalStateException(current + " doesn't support getArray()");
}
- JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider());
+ JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT);
return jsonReader.readArray();
}
@@ -81,7 +81,7 @@
switch (current) {
case START_ARRAY:
case START_OBJECT:
- JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider());
+ JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT);
return jsonReader.readValue();
case VALUE_TRUE:
return JsonValue.TRUE;
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
index 5ea8c65..1ee44fc 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
@@ -35,6 +35,7 @@
import org.apache.johnzon.core.util.ArrayUtil;
class JsonArrayBuilderImpl implements JsonArrayBuilder, Serializable {
+ private RejectDuplicateKeysMode rejectDuplicateKeysMode;
private List<JsonValue> tmpList;
private BufferStrategy.BufferProvider<char[]> bufferProvider;
@@ -43,13 +44,17 @@
}
public JsonArrayBuilderImpl(final JsonArray initialData,
- final BufferStrategy.BufferProvider<char[]> provider) {
+ final BufferStrategy.BufferProvider<char[]> provider,
+ final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
this.tmpList = new ArrayList<>(initialData);
this.bufferProvider = provider;
+ this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
}
- public JsonArrayBuilderImpl(final Collection<?> initialData, final BufferStrategy.BufferProvider<char[]> provider) {
+ public JsonArrayBuilderImpl(final Collection<?> initialData, final BufferStrategy.BufferProvider<char[]> provider,
+ final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
this.bufferProvider = provider;
+ this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
this.tmpList = new ArrayList<>();
if (!initialData.isEmpty()) {
for (Object initialValue : initialData) {
@@ -220,12 +225,12 @@
} else if (value instanceof String) {
add((String) value);
} else if (value instanceof Map) {
- add(new JsonObjectBuilderImpl(Map.class.cast(value), bufferProvider).build());
+ add(new JsonObjectBuilderImpl(Map.class.cast(value), bufferProvider, rejectDuplicateKeysMode).build());
} else if (value instanceof Collection) {
- add(new JsonArrayBuilderImpl(Collection.class.cast(value), bufferProvider).build());
+ add(new JsonArrayBuilderImpl(Collection.class.cast(value), bufferProvider, rejectDuplicateKeysMode).build());
} else if (value.getClass().isArray()) {
final Collection<Object> collection = ArrayUtil.newCollection(value);
- add(new JsonArrayBuilderImpl(collection, bufferProvider).build());
+ add(new JsonArrayBuilderImpl(collection, bufferProvider, rejectDuplicateKeysMode).build());
} else {
throw new JsonException("Illegal JSON type! type=" + value.getClass());
}
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java
index f0cb8f5..efd10fe 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java
@@ -18,8 +18,12 @@
*/
package org.apache.johnzon.core;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonBuilderFactory;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
import java.io.Serializable;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -27,32 +31,26 @@
import java.util.Map;
import java.util.logging.Logger;
-import javax.json.JsonArray;
-import javax.json.JsonArrayBuilder;
-import javax.json.JsonBuilderFactory;
-import javax.json.JsonObject;
-import javax.json.JsonObjectBuilder;
-
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
class JsonBuilderFactoryImpl implements JsonBuilderFactory, Serializable {
private final Map<String, Object> internalConfig = new HashMap<String, Object>();
+ private RejectDuplicateKeysMode rejectDuplicateKeysMode;
private BufferStrategy.BufferProvider<char[]> bufferProvider;
- private static final String[] SUPPORTED_CONFIG_KEYS = new String[] {
- // nothing yet
- };
+ private static final List<String> SUPPORTED_CONFIG_KEYS = RejectDuplicateKeysMode.CONFIG_KEYS;
protected JsonBuilderFactoryImpl() {
// no-op: serialization
}
- JsonBuilderFactoryImpl(final Map<String, ?> config, final BufferStrategy.BufferProvider<char[]> bufferProvider) {
+ JsonBuilderFactoryImpl(final Map<String, ?> config, final BufferStrategy.BufferProvider<char[]> bufferProvider,
+ final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
this.bufferProvider = bufferProvider;
- if (config != null && config.size() > 0) {
- final List<String> supportedConfigKeys = Arrays.asList(SUPPORTED_CONFIG_KEYS);
+ this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
+ if (config != null && !config.isEmpty()) {
for (String configKey : config.keySet()) {
- if(supportedConfigKeys.contains(configKey)) {
+ if(SUPPORTED_CONFIG_KEYS.contains(configKey)) {
internalConfig.put(configKey, config.get(configKey));
} else {
Logger.getLogger(this.getClass().getName())
@@ -64,28 +62,28 @@
@Override
public JsonObjectBuilder createObjectBuilder() {
- return new JsonObjectBuilderImpl(emptyMap(), bufferProvider);
+ return new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
}
@Override
public JsonObjectBuilder createObjectBuilder(JsonObject initialData) {
- return new JsonObjectBuilderImpl(initialData, bufferProvider);
+ return new JsonObjectBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode);
}
@Override
public JsonArrayBuilder createArrayBuilder() {
- return new JsonArrayBuilderImpl(emptyList(), bufferProvider);
+ return new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode);
}
@Override
public JsonArrayBuilder createArrayBuilder(JsonArray initialData) {
- return new JsonArrayBuilderImpl(initialData, bufferProvider);
+ return new JsonArrayBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode);
}
@Override
public JsonArrayBuilder createArrayBuilder(Collection<?> initialData) {
- return new JsonArrayBuilderImpl(initialData, bufferProvider);
+ return new JsonArrayBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode);
}
@Override
@@ -95,7 +93,7 @@
@Override
public JsonObjectBuilder createObjectBuilder(Map<String, Object> initialValues) {
- return new JsonObjectBuilderImpl(initialValues, bufferProvider);
+ return new JsonObjectBuilderImpl(initialValues, bufferProvider, rejectDuplicateKeysMode);
}
}
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchDiff.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchDiff.java
index 1ca3bf9..3825229 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchDiff.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchDiff.java
@@ -45,7 +45,7 @@
}
private JsonValue diff(JsonValue source, JsonValue target) {
- JsonObjectBuilder builder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider);
+ JsonObjectBuilder builder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, RejectDuplicateKeysMode.DEFAULT);
if (isJsonObject(source) && isJsonObject(target)) {
JsonObject srcObj = source.asJsonObject();
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchImpl.java
index 56518cd..9d40f05 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchImpl.java
@@ -58,7 +58,7 @@
}
private JsonValue applyJsonObjectPatch(JsonObject jsonObject, JsonObject patch) {
- JsonObjectBuilder builder = new JsonObjectBuilderImpl(jsonObject, bufferProvider);
+ JsonObjectBuilder builder = new JsonObjectBuilderImpl(jsonObject, bufferProvider, RejectDuplicateKeysMode.DEFAULT);
for (Map.Entry<String, JsonValue> patchAttrib : patch.entrySet()) {
String attribName = patchAttrib.getKey();
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
index fafcc74..2eb4ab0 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
@@ -36,6 +36,7 @@
import org.apache.johnzon.core.util.ArrayUtil;
class JsonObjectBuilderImpl implements JsonObjectBuilder, Serializable {
+ private RejectDuplicateKeysMode rejectDuplicateKeysMode;
private BufferStrategy.BufferProvider<char[]> bufferProvider;
private Map<String, JsonValue> attributeMap = new LinkedHashMap<>();
@@ -44,14 +45,18 @@
}
public JsonObjectBuilderImpl(final JsonObject initialData,
- final BufferStrategy.BufferProvider<char[]> bufferProvider) {
+ final BufferStrategy.BufferProvider<char[]> bufferProvider,
+ final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
this.bufferProvider = bufferProvider;
- attributeMap = new LinkedHashMap<>(initialData);
+ this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
+ this.attributeMap = new LinkedHashMap<>(initialData);
}
public JsonObjectBuilderImpl(final Map<String, Object> initialValues,
- final BufferStrategy.BufferProvider<char[]> bufferProvider) {
+ final BufferStrategy.BufferProvider<char[]> bufferProvider,
+ final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
this.bufferProvider = bufferProvider;
+ this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
if (!initialValues.isEmpty()) {
for (Map.Entry<String, Object> entry : initialValues.entrySet()) {
add(entry.getKey(), entry.getValue());
@@ -83,12 +88,12 @@
} else if (value == null) {
addNull(name);
} else if (value instanceof Map) {
- add(name, new JsonObjectBuilderImpl(Map.class.cast(value), bufferProvider).build());
+ add(name, new JsonObjectBuilderImpl(Map.class.cast(value), bufferProvider, rejectDuplicateKeysMode).build());
} else if (value instanceof Collection) {
- add(name, new JsonArrayBuilderImpl(Collection.class.cast(value), bufferProvider).build());
+ add(name, new JsonArrayBuilderImpl(Collection.class.cast(value), bufferProvider, rejectDuplicateKeysMode).build());
} else if (value.getClass().isArray()) {
final Collection<Object> collection = ArrayUtil.newCollection(value);
- add(name, new JsonArrayBuilderImpl(collection, bufferProvider).build());
+ add(name, new JsonArrayBuilderImpl(collection, bufferProvider, rejectDuplicateKeysMode).build());
} else {
throw new JsonException("Illegal JSON type! name=" + name + " type=" + value.getClass());
}
@@ -172,12 +177,11 @@
return this;
}
- private void putValue(String name, JsonValue value){
+ private void putValue(final String name, final JsonValue value){
if(name == null || value == null) {
throw new NullPointerException("name or value/builder must not be null");
}
-
- attributeMap.put(name, value);
+ rejectDuplicateKeysMode.put().put(attributeMap, name, value);
}
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
index c3147d9..1bfcd71 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
@@ -68,7 +68,7 @@
private final JsonGeneratorFactory generatorFactory = new JsonGeneratorFactoryImpl(null);
private final JsonWriterFactory writerFactory = new JsonWriterFactoryImpl(null);
private final Supplier<JsonBuilderFactory> builderFactory = new Cached<>(() ->
- new JsonBuilderFactoryImpl(null, bufferProvider.get()));
+ new JsonBuilderFactoryImpl(null, bufferProvider.get(), RejectDuplicateKeysMode.DEFAULT));
private final JsonPointerFactory jsonPointerFactory;
public JsonProviderImpl() {
@@ -201,7 +201,7 @@
public JsonBuilderFactory createBuilderFactory(final Map<String, ?> config) {
final JsonBuilderFactory builderFactory = this.builderFactory.get();
return (config == null || config.isEmpty()) ?
- builderFactory : new JsonBuilderFactoryImpl(config, bufferProvider.get());
+ builderFactory : new JsonBuilderFactoryImpl(config, bufferProvider.get(), RejectDuplicateKeysMode.from(config));
}
@Override
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java
index 4f98812..233f8b0 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java
@@ -18,8 +18,6 @@
*/
package org.apache.johnzon.core;
-import static java.util.Arrays.asList;
-
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.Charset;
@@ -32,33 +30,37 @@
import javax.json.stream.JsonParser;
class JsonReaderFactoryImpl extends AbstractJsonFactory implements JsonReaderFactory {
- static final Collection<String> SUPPORTED_CONFIG_KEYS = asList(
+ static final Collection<String> SUPPORTED_CONFIG_KEYS = RejectDuplicateKeysMode.CONFIG_KEYS;
- );
private final JsonParserFactoryImpl parserFactory;
+ private final RejectDuplicateKeysMode rejectDuplicateKeys;
JsonReaderFactoryImpl(final Map<String, ?> config) {
super(config, SUPPORTED_CONFIG_KEYS, JsonParserFactoryImpl.SUPPORTED_CONFIG_KEYS);
+ if (!internalConfig.isEmpty()) {
+ RejectDuplicateKeysMode.CONFIG_KEYS.forEach(internalConfig::remove);
+ }
this.parserFactory = new JsonParserFactoryImpl(internalConfig);
+ this.rejectDuplicateKeys = RejectDuplicateKeysMode.from(config);
}
@Override
public JsonReader createReader(final Reader reader) {
- return new JsonReaderImpl(parserFactory.createInternalParser(reader), parserFactory.getValueBufferProvider());
+ return new JsonReaderImpl(parserFactory.createInternalParser(reader), parserFactory.getValueBufferProvider(), rejectDuplicateKeys);
}
@Override
public JsonReader createReader(final InputStream in) {
- return new JsonReaderImpl(parserFactory.createInternalParser(in), parserFactory.getValueBufferProvider());
+ return new JsonReaderImpl(parserFactory.createInternalParser(in), parserFactory.getValueBufferProvider(), rejectDuplicateKeys);
}
@Override
public JsonReader createReader(final InputStream in, final Charset charset) {
- return new JsonReaderImpl(parserFactory.createInternalParser(in, charset), parserFactory.getValueBufferProvider());
+ return new JsonReaderImpl(parserFactory.createInternalParser(in, charset), parserFactory.getValueBufferProvider(), rejectDuplicateKeys);
}
public JsonReader createReader(final JsonParser parser) {
- return new JsonReaderImpl(parser, parserFactory.getValueBufferProvider());
+ return new JsonReaderImpl(parser, parserFactory.getValueBufferProvider(), rejectDuplicateKeys);
}
@Override
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
index 24de161..969ad9a 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
@@ -36,12 +36,14 @@
public class JsonReaderImpl implements JsonReader {
private final JohnzonJsonParser parser;
private final BufferStrategy.BufferProvider<char[]> bufferProvider;
+ private final RejectDuplicateKeysMode rejectDuplicateKeysMode;
private boolean closed = false;
private boolean subStreamReader;
- public JsonReaderImpl(final JsonParser parser, final BufferStrategy.BufferProvider<char[]> bufferProvider) {
- this(parser, false, bufferProvider);
+ public JsonReaderImpl(final JsonParser parser, final BufferStrategy.BufferProvider<char[]> bufferProvider,
+ final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
+ this(parser, false, bufferProvider, rejectDuplicateKeysMode);
}
/**
@@ -51,7 +53,8 @@
* @param bufferProvider buffer provider for toString of created instances.
*/
public JsonReaderImpl(final JsonParser parser, boolean subStreamReader,
- final BufferStrategy.BufferProvider<char[]> bufferProvider) {
+ final BufferStrategy.BufferProvider<char[]> bufferProvider,
+ final RejectDuplicateKeysMode rejectDuplicateKeys) {
this.bufferProvider = bufferProvider;
if (parser instanceof JohnzonJsonParser) {
this.parser = (JohnzonJsonParser) parser;
@@ -60,6 +63,7 @@
}
this.subStreamReader = subStreamReader;
+ this.rejectDuplicateKeysMode = rejectDuplicateKeys;
}
@Override
@@ -85,14 +89,14 @@
switch (next) {
case START_OBJECT:
- final JsonObjectBuilder objectBuilder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider);
+ final JsonObjectBuilder objectBuilder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
parseObject(objectBuilder);
if (!subStreamReader && parser.hasNext()) {
throw new JsonParsingException("Expected end of file", parser.getLocation());
}
return objectBuilder.build();
case START_ARRAY:
- final JsonArrayBuilder arrayBuilder = new JsonArrayBuilderImpl(emptyList(), bufferProvider);
+ final JsonArrayBuilder arrayBuilder = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode);
parseArray(arrayBuilder);
if (!subStreamReader && parser.hasNext()) {
throw new JsonParsingException("Expected end of file", parser.getLocation());
@@ -178,13 +182,13 @@
break;
case START_OBJECT:
- JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider);
+ JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
parseObject(subObject);
builder.add(key, subObject);
break;
case START_ARRAY:
- JsonArrayBuilder subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider);
+ JsonArrayBuilder subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode);
parseArray(subArray);
builder.add(key, subArray);
break;
@@ -238,14 +242,14 @@
break;
case START_OBJECT:
- JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider);
+ JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
parseObject(subObject);
builder.add(subObject);
break;
case START_ARRAY:
JsonArrayBuilder subArray = null;
- parseArray(subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider));
+ parseArray(subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode));
builder.add(subArray);
break;
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/RejectDuplicateKeysMode.java b/johnzon-core/src/main/java/org/apache/johnzon/core/RejectDuplicateKeysMode.java
new file mode 100644
index 0000000..5e48eea
--- /dev/null
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/RejectDuplicateKeysMode.java
@@ -0,0 +1,71 @@
+/*
+ * 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.core;
+
+import javax.json.JsonException;
+import javax.json.JsonValue;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+
+import static java.util.Arrays.asList;
+
+public enum RejectDuplicateKeysMode {
+ DEFAULT(Map::put),
+ TRUE((map, k, v) -> {
+ if (map.put(k, v) != null) {
+ throw new JsonException("Rejected key: '" + k + "', already present");
+ }
+ });
+
+ static final List<String> CONFIG_KEYS = asList(
+ "johnzon.rejectDuplicateKeys", // our specific one
+ "org.glassfish.json.rejectDuplicateKeys" // the spec includes it (yes :facepalm:)
+ );
+
+ public static RejectDuplicateKeysMode from(final Map<String, ?> config) {
+ if (config == null) {
+ return DEFAULT;
+ }
+ return CONFIG_KEYS.stream()
+ .map(config::get)
+ .filter(Objects::nonNull)
+ .findFirst()
+ .map(String::valueOf)
+ .map(it -> "false".equalsIgnoreCase(it) ? "DEFAULT" : it) // alias to avoid to add an enum value for nothing
+ .map(it -> valueOf(it.toUpperCase(Locale.ROOT).trim()))
+ .orElse(DEFAULT);
+ }
+
+ private final Put put;
+
+ RejectDuplicateKeysMode(final Put put) {
+ this.put = put;
+ }
+
+ public Put put() {
+ return put;
+ }
+
+ @FunctionalInterface
+ public interface Put {
+ void put(final Map<String, JsonValue> receiptor, final String key, final JsonValue value);
+ }
+}
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java
index 3cfd22b..be97361 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java
@@ -28,6 +28,7 @@
import static org.junit.Assert.assertEquals;
import javax.json.Json;
+import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonValue;
@@ -36,6 +37,14 @@
import org.junit.Test;
public class JsonObjectBuilderImplTest {
+ @Test(expected = JsonException.class)
+ public void rejectedKeys() {
+ Json.createBuilderFactory(singletonMap("johnzon.rejectDuplicateKeys", true))
+ .createObjectBuilder()
+ .add("foo", 1)
+ .add("foo", 2);
+ }
+
@Test
public void createObjectBuilderMapSupport() {
final Map<String, Object> initial = new HashMap<>();
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java
index becdf5f..5da7fa7 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java
@@ -19,6 +19,7 @@
package org.apache.johnzon.core;
import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonMap;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -36,6 +37,7 @@
import javax.json.Json;
import javax.json.JsonArray;
+import javax.json.JsonException;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonReader;
@@ -64,6 +66,14 @@
return Collections.EMPTY_MAP;
}
+ @Test(expected = JsonException.class)
+ public void rejectedKeys() {
+ Json.createReaderFactory(singletonMap("johnzon.rejectDuplicateKeys", true)).createReader(new StringReader("{" +
+ "\"a\":1," +
+ "\"a\":2" +
+ "}")).readObject();
+ }
+
@Test(expected = JsonParsingException.class)
public void badTypeObject() {
Json.createReaderFactory(getFactoryConfig()).createReader(new StringReader("[]")).readObject();