You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by st...@apache.org on 2018/05/04 19:37:47 UTC
[5/6] johnzon git commit: backporting changes from master to the
JSON_P-1.0 branch
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
index b610995..2a2a12d 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
@@ -18,17 +18,47 @@
*/
package org.apache.johnzon.core;
-import java.math.BigInteger;
+import org.junit.Assert;
+import org.junit.Test;
import javax.json.Json;
import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.math.BigInteger;
-import org.junit.Assert;
-import org.junit.Test;
-
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
public class JsonNumberTest {
+ @Test
+ public void nonZeroFractional() {
+ final JsonNumber number = Json.createArrayBuilder()
+ .add(12345.6489)
+ .build()
+ .getJsonNumber(0);
+ try {
+ number.intValueExact();
+ fail();
+ } catch (final ArithmeticException ae) {
+ // ok
+ }
+ try {
+ number.longValueExact();
+ fail();
+ } catch (final ArithmeticException ae) {
+ // ok
+ }
+ }
+ @Test
+ public void equals() {
+ final JsonNumber a = Json.createObjectBuilder().add("a", 1).build().getJsonNumber("a");
+ final JsonNumber b = Json.createObjectBuilder().add("b", 1.1).build().getJsonNumber("b");
+ assertFalse(a.equals(b));
+ assertFalse(b.equals(a));
+ }
@Test(expected=ArithmeticException.class)
public void testBigIntegerExact() {
@@ -48,4 +78,21 @@ public class JsonNumberTest {
}
+ @Test
+ public void testBigIntegerButFromJustALongTooLong() {
+ final StringWriter writer = new StringWriter();
+ Json.createGenerator(writer).writeStartObject().write("value", new BigInteger("10002000000000000000")).writeEnd().close();
+ final String asJson = writer.toString();
+ final JsonNumber jsonNumber = Json.createReader(new StringReader(asJson)).readObject().getJsonNumber("value");
+ Assert.assertEquals(new BigInteger("10002000000000000000"), jsonNumber.bigIntegerValue());
+ }
+
+ @Test
+ public void testHashCode() {
+ JsonNumber a = Json.createObjectBuilder().add("a", 1).build().getJsonNumber("a");
+ JsonNumber b = Json.createObjectBuilder().add("b", 1.1).build().getJsonNumber("b");
+
+ Assert.assertEquals(a.hashCode(), a.bigDecimalValue().hashCode());
+ Assert.assertEquals(b.hashCode(), b.bigDecimalValue().hashCode());
+ }
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java
----------------------------------------------------------------------
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 098967e..7ca990d 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
@@ -21,15 +21,29 @@ package org.apache.johnzon.core;
import static org.junit.Assert.assertEquals;
import javax.json.Json;
+import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import org.junit.Test;
public class JsonObjectBuilderImplTest {
@Test
- public void build() {
+ public void testBuild() {
final JsonObjectBuilder builder = Json.createObjectBuilder();
builder.add("a", "b");
- assertEquals("{\"a\":\"b\"}", builder.build().toString());
+ JsonObject jsonObject = builder.build();
+ assertEquals("{\"a\":\"b\"}", jsonObject.toString());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullCheckValue() {
+ final JsonObjectBuilder builder = Json.createObjectBuilder();
+ builder.add("a", (Integer) null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullCheckName() {
+ final JsonObjectBuilder builder = Json.createObjectBuilder();
+ builder.add(null, "b");
}
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectImplTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectImplTest.java
index e7b5c06..1557070 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectImplTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectImplTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import javax.json.Json;
import javax.json.JsonObject;
@@ -32,6 +33,22 @@ import org.junit.Test;
public class JsonObjectImplTest {
@Test
+ public void boolErrors() {
+ {
+ final JsonObject val = Json.createObjectBuilder().add("a", true).build();
+ assertTrue(val.getBoolean("a"));
+ }
+ {
+ final JsonObject val = Json.createObjectBuilder().add("a", "wrong").build();
+ try {
+ val.getBoolean("a");
+ fail();
+ } catch (final ClassCastException cce) {
+ // ok
+ }
+ }
+ }
+ @Test
public void objectToString() {
final JsonObjectBuilder ob = Json.createObjectBuilder();
ob.add("a", new JsonStringImpl("b"));
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
index e035789..2e0df04 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
@@ -229,7 +229,7 @@ public class JsonParserTest {
ob.add("d", ab);
- final JsonParser parser = Json.createParserFactory(Collections.<String, Object>emptyMap()).createParser(ob.build());
+ final JsonParser parser = Json.createParserFactory(Collections.EMPTY_MAP).createParser(ob.build());
assertNotNull(parser);
assertSimple(parser);
}
@@ -247,18 +247,19 @@ public class JsonParserTest {
assertNotNull(parser);
assertSimple(parser);
}
-
+
@Test
public void simpleUTF16LE() {
final JsonParser parser = Json.createParserFactory(null).createParser(Thread.currentThread()
- .getContextClassLoader().getResourceAsStream("json/simple_utf16le.json"),UTF_16LE);
+ .getContextClassLoader().getResourceAsStream("json/simple_utf16le.json"), UTF_16LE);
assertNotNull(parser);
assertSimple(parser);
}
@Test
public void simpleUTF16LEAutoDetect() {
- final JsonParser parser = Json.createParserFactory(null).createParser(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/simple_utf16le.json"));
+ final JsonParser parser = Json.createParserFactory(null).createParser(Thread.currentThread().
+ getContextClassLoader().getResourceAsStream("json/simple_utf16le.json"));
assertNotNull(parser);
assertSimple(parser);
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java
----------------------------------------------------------------------
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 e9d3d74..fcb8182 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
@@ -42,13 +42,13 @@ import javax.json.JsonReaderFactory;
import javax.json.JsonString;
import javax.json.JsonStructure;
import javax.json.JsonValue;
+import javax.json.stream.JsonParsingException;
import org.junit.Test;
public class JsonReaderImplTest {
-
public JsonReaderImplTest() {
if (!Charset.defaultCharset().equals(Charset.forName("UTF-8"))) {
System.err.println("Default charset is " + Charset.defaultCharset() + ", must must be UTF-8");
@@ -63,6 +63,16 @@ public class JsonReaderImplTest {
return Collections.EMPTY_MAP;
}
+ @Test(expected = JsonParsingException.class)
+ public void badTypeObject() {
+ Json.createReaderFactory(getFactoryConfig()).createReader(new StringReader("[]")).readObject();
+ }
+
+ @Test(expected = JsonParsingException.class)
+ public void badTypeArray() {
+ Json.createReaderFactory(getFactoryConfig()).createReader(new StringReader("{}")).readArray();
+ }
+
@Test
public void simple() {
final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
@@ -173,7 +183,7 @@ public class JsonReaderImplTest {
assertEquals("hallo\u20acö\uffff \u08a5 থ?ß§$%&´'`*+#\udbff\udfff", object.getString("নa"));
reader.close();
}
-
+
@Test
public void specialKeysWithStringAsByteArrayInputStream() {
final String s = "{\"\\\"a\":\"\u0055\",\"\u0055\":\"test2\"}";
@@ -348,7 +358,7 @@ public class JsonReaderImplTest {
assertEquals(-2, array.getInt(1));
reader.close();
}
-
+
@Test
public void simple2BadBufferSize8() {
final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
@@ -435,8 +445,8 @@ public class JsonReaderImplTest {
@Test
public void stringescapeVariousBufferSizes() {
- final int[] buffersizes = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 32, 64, 128, 1024, 8192 };
+ final int[] buffersizes = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 32, 64, 128, 1024, 8192};
for (final int buffersize : buffersizes) {
final String value = String.valueOf(buffersize);
@@ -474,7 +484,7 @@ public class JsonReaderImplTest {
public void testGrowingString() throws Throwable {
JsonReaderFactory factory = Json.createReaderFactory(null);
StringBuilder sb = new StringBuilder();
- for (int i = 0; i < 40000; i++) {
+ for (int i = 0; i < 10000; i++) {
sb.append('x');
String growingString = sb.toString();
String str = "[4, \"\", \"" + growingString + "\", \"\", \"" + growingString + "\", \"\", 400]";
@@ -507,7 +517,7 @@ public class JsonReaderImplTest {
JsonReaderFactory factory = Json.createReaderFactory(config);
StringBuilder sb = new StringBuilder();
- for (int i = 0; i < 1000; i++) {
+ for (int i = 0; i < 100; i++) {
sb.append('x');
String name = sb.toString();
String str = "[4, \"\", \"" + name + "\", \"\", \"" + name + "\", \"\", 400]";
@@ -558,4 +568,12 @@ public class JsonReaderImplTest {
assertEquals(1234.5, JsonNumber.class.cast(value).doubleValue(), 0.);
}
}
+
+
+ @Test(expected = JsonParsingException.class)
+ public void testInvalidNumber() {
+ String jsonWithIllegalNumber = "{\"val\":12.34-2}";
+ JsonReaderImpl.class.cast(Json.createReader(new StringReader(jsonWithIllegalNumber))).readObject();
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/OverflowTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/OverflowTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/OverflowTest.java
new file mode 100644
index 0000000..a6879cf
--- /dev/null
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/OverflowTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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 org.junit.Assert;
+import org.junit.Test;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonWriter;
+import javax.json.JsonWriterFactory;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.HashMap;
+
+import static org.junit.Assert.assertEquals;
+
+public class OverflowTest {
+ @Test
+ public void ok() {
+ // normal content size
+ Json.createReaderFactory(new HashMap<String, Object>() {{
+ put(JsonParserFactoryImpl.MAX_STRING_LENGTH, "10");
+ put(JsonParserFactoryImpl.BUFFER_LENGTH, "2");
+ }}).createReader(new StringReader("{\"a\":\"b\",\n\"another\":\"value\"}")).readObject();
+
+ // oversized
+ final JsonObject object = Json.createReaderFactory(new HashMap<String, Object>() {{
+ put(JsonParserFactoryImpl.MAX_STRING_LENGTH, "10");
+ put(JsonParserFactoryImpl.BUFFER_LENGTH, "2");
+ }}).createReader(new StringReader("{\"a\":\"b\",\n\"another\":\"value very long\"}")).readObject();
+ assertEquals("value very long", object.getString("another"));
+ }
+
+ @Test(expected = ArrayIndexOutOfBoundsException.class)
+ public void ko() {
+ Json.createReaderFactory(new HashMap<String, Object>() {{
+ put(JsonParserFactoryImpl.MAX_STRING_LENGTH, "10");
+ put(JsonParserFactoryImpl.BUFFER_LENGTH, "2");
+ put(JsonParserFactoryImpl.AUTO_ADJUST_STRING_BUFFER, "false");
+ }}).createReader(new StringReader("{\"another\":\"value too long\"}")).readObject();
+ }
+
+ @Test
+ public void testVeryLargeJson() {
+ JsonWriterFactory writerFactory = Json.createWriterFactory(new HashMap<String, Object>() {{
+ put(JsonParserFactoryImpl.BUFFER_LENGTH, "256");
+ }});
+
+ int itemSize = 50000;
+
+ StringWriter sw = new StringWriter();
+ JsonWriter writer = writerFactory.createWriter(sw);
+
+ JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+ for (int i = 0; i < itemSize; i++) {
+ arrayBuilder.add("0123456789012345-" + i);
+ }
+ writer.writeArray(arrayBuilder.build());
+
+ String json = sw.toString();
+ System.out.println("Created a JSON of size " + json.length() + " bytes");
+
+ // read it back in
+ JsonArray jsonArray = Json.createReader(new StringReader(json)).readArray();
+ Assert.assertEquals(itemSize, jsonArray.size());
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/resources/json/jsonPointerTest.json
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/resources/json/jsonPointerTest.json b/johnzon-core/src/test/resources/json/jsonPointerTest.json
new file mode 100644
index 0000000..8cdc1c9
--- /dev/null
+++ b/johnzon-core/src/test/resources/json/jsonPointerTest.json
@@ -0,0 +1,15 @@
+{
+ "foo": [
+ "bar",
+ "baz"
+ ],
+ "": 0,
+ "a/b": 1,
+ "c%d": 2,
+ "e^f": 3,
+ "g|h": 4,
+ "i\\j": 5,
+ "k\"l": 6,
+ " ": 7,
+ "m~n": 8
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-distribution/pom.xml
----------------------------------------------------------------------
diff --git a/johnzon-distribution/pom.xml b/johnzon-distribution/pom.xml
index 1240af0..ccb3d01 100644
--- a/johnzon-distribution/pom.xml
+++ b/johnzon-distribution/pom.xml
@@ -32,24 +32,23 @@
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-json_1.0_spec</artifactId>
- <version>${jsonspecversion}</version>
+ <version>${geronimo-jsonp.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-json_1.0_spec</artifactId>
- <version>${jsonspecversion}</version>
+ <version>${geronimo-jsonp.version}</version>
<scope>compile</scope>
<classifier>sources</classifier>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-json_1.0_spec</artifactId>
- <version>${jsonspecversion}</version>
+ <version>${geronimo-jsonp.version}</version>
<scope>compile</scope>
<classifier>javadoc</classifier>
</dependency>
-
<dependency>
<groupId>org.apache.johnzon</groupId>
<artifactId>johnzon-core</artifactId>
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
index dd8b79c..e543804 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
@@ -19,6 +19,7 @@
package org.apache.johnzon.jaxrs;
import org.apache.johnzon.mapper.MapperBuilder;
+import org.apache.johnzon.mapper.SerializeValueFilter;
import org.apache.johnzon.mapper.access.AccessMode;
import javax.json.JsonReaderFactory;
@@ -34,6 +35,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.util.Comparator;
import java.util.List;
@@ -116,6 +118,10 @@ public class ConfigurableJohnzonProvider<T> implements MessageBodyWriter<T>, Mes
}
}
+ public void setFailOnUnknownProperties(final boolean active) {
+ builder.setFailOnUnknownProperties(active);
+ }
+
public void setSupportConstructors(final boolean supportConstructors) {
builder.setSupportConstructors(supportConstructors);
}
@@ -207,4 +213,33 @@ public class ConfigurableJohnzonProvider<T> implements MessageBodyWriter<T>, Mes
public void setPrimitiveConverters(final boolean val) {
builder.setPrimitiveConverters(val);
}
+
+ public MapperBuilder setDeduplicateObjects(boolean deduplicateObjects) {
+ return builder.setDeduplicateObjects(deduplicateObjects);
+ }
+
+ public void setSerializeValueFilter(final String val) {
+ try {
+ builder.setSerializeValueFilter(SerializeValueFilter.class.cast(
+ Thread.currentThread().getContextClassLoader().loadClass(val).getConstructor().newInstance()));
+ } catch (final InstantiationException e) {
+ throw new IllegalArgumentException(e);
+ } catch (final IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ } catch (final NoSuchMethodException e) {
+ throw new IllegalArgumentException(e);
+ } catch (final ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalArgumentException(e.getCause());
+ }
+ }
+
+ public void setUseBigDecimalForFloats(final boolean useBigDecimalForFloats) {
+ builder.setUseBigDecimalForFloats(useBigDecimalForFloats);
+ }
+
+ public void setAutoAdjustStringBuffers(final boolean autoAdjustStringBuffers) {
+ builder.setAutoAdjustStringBuffers(autoAdjustStringBuffers);
+ }
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java
index f3d9a18..42fcbf0 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyReader.java
@@ -58,8 +58,10 @@ public class JohnzonMessageBodyReader<T> extends IgnorableTypes implements Messa
public boolean isReadable(final Class<?> rawType, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {
return !isIgnored(rawType)
- && InputStream.class != genericType && Reader.class != genericType && Response.class != genericType
- && String.class != genericType
+ && !InputStream.class.isAssignableFrom(rawType)
+ && !Reader.class.isAssignableFrom(rawType)
+ && !Response.class.isAssignableFrom(rawType)
+ && !CharSequence.class.isAssignableFrom(rawType)
&& !JsonStructure.class.isAssignableFrom(rawType);
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java
index e6a8d36..6a3e163 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/JohnzonMessageBodyWriter.java
@@ -65,12 +65,12 @@ public class JohnzonMessageBodyWriter<T> extends IgnorableTypes implements Messa
public boolean isWriteable(final Class<?> rawType, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {
return !isIgnored(rawType)
- && InputStream.class != genericType
- && OutputStream.class != genericType
- && Writer.class != genericType
- && StreamingOutput.class != genericType
- && String.class != genericType
- && Response.class != genericType
+ && !InputStream.class.isAssignableFrom(rawType)
+ && !OutputStream.class.isAssignableFrom(rawType)
+ && !Writer.class.isAssignableFrom(rawType)
+ && !StreamingOutput.class.isAssignableFrom(rawType)
+ && !CharSequence.class.isAssignableFrom(rawType)
+ && !Response.class.isAssignableFrom(rawType)
&& !JsonStructure.class.isAssignableFrom(rawType);
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
index 4df4a7c..a895e07 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
@@ -19,6 +19,7 @@
package org.apache.johnzon.jaxrs;
import org.apache.johnzon.mapper.MapperBuilder;
+import org.apache.johnzon.mapper.SerializeValueFilter;
import org.apache.johnzon.mapper.access.AccessMode;
import javax.json.JsonReaderFactory;
@@ -34,6 +35,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.util.Comparator;
import java.util.List;
@@ -43,14 +45,14 @@ import static java.util.Arrays.asList;
@Provider
@Produces({
- "*/json",
- "*/*+json", "*/x-json",
- "*/javascript", "*/x-javascript"
+ "*/json",
+ "*/*+json", "*/x-json",
+ "*/javascript", "*/x-javascript"
})
@Consumes({
- "*/json",
- "*/*+json", "*/x-json",
- "*/javascript", "*/x-javascript"
+ "*/json",
+ "*/*+json", "*/x-json",
+ "*/javascript", "*/x-javascript"
})
public class WildcardConfigurableJohnzonProvider<T> implements MessageBodyWriter<T>, MessageBodyReader<T> {
// build/configuration
@@ -124,6 +126,10 @@ public class WildcardConfigurableJohnzonProvider<T> implements MessageBodyWriter
}
}
+ public void setFailOnUnknownProperties(final boolean active) {
+ builder.setFailOnUnknownProperties(active);
+ }
+
public void setSupportConstructors(final boolean supportConstructors) {
builder.setSupportConstructors(supportConstructors);
}
@@ -215,4 +221,25 @@ public class WildcardConfigurableJohnzonProvider<T> implements MessageBodyWriter
public void setPrimitiveConverters(final boolean val) {
builder.setPrimitiveConverters(val);
}
+
+ public void setUseBigDecimalForFloats(final boolean useBigDecimalForFloats) {
+ builder.setUseBigDecimalForFloats(useBigDecimalForFloats);
+ }
+
+ public void setSerializeValueFilter(final String val) {
+ try {
+ builder.setSerializeValueFilter(SerializeValueFilter.class.cast(
+ Thread.currentThread().getContextClassLoader().loadClass(val).getConstructor().newInstance()));
+ } catch (final InstantiationException e) {
+ throw new IllegalArgumentException(e);
+ } catch (final IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ } catch (final NoSuchMethodException e) {
+ throw new IllegalArgumentException(e);
+ } catch (final ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalArgumentException(e.getCause());
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/JohnzonProviderTest.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/JohnzonProviderTest.java b/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/JohnzonProviderTest.java
index 6af6f68..a77752d 100644
--- a/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/JohnzonProviderTest.java
+++ b/johnzon-jaxrs/src/test/java/org/apache/johnzon/jaxrs/JohnzonProviderTest.java
@@ -18,14 +18,20 @@
*/
package org.apache.johnzon.jaxrs;
-import org.apache.cxf.endpoint.Server;
-import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
-import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
-import org.apache.cxf.transport.local.LocalConduit;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -34,24 +40,25 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.Entity;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.StreamingOutput;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.transport.local.LocalConduit;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
public class JohnzonProviderTest {
+
private final static String ENDPOINT_ADDRESS = "local://johnzon";
+
private static Server server;
@BeforeClass
@@ -72,7 +79,8 @@ public class JohnzonProviderTest {
@Test
public void asParam() {
- final String result = client().path("johnzon").type(MediaType.APPLICATION_JSON_TYPE).post(new Johnzon("client")).readEntity(String.class);
+ final String result = client().path("johnzon").type(MediaType.APPLICATION_JSON_TYPE).post(new Johnzon("client"))
+ .readEntity(String.class);
assertTrue(Boolean.parseBoolean(result));
}
@@ -89,6 +97,19 @@ public class JohnzonProviderTest {
}
@Test
+ public void untypedStreamOutput() {
+ final StreamingOutput impl = new StreamingOutput() {
+
+ @Override
+ public void write(final OutputStream outputStream) throws IOException, WebApplicationException {
+ // no-op
+ }
+ };
+ assertFalse(new JohnzonMessageBodyWriter().isWriteable(impl.getClass(), impl.getClass(), new Annotation[0],
+ MediaType.APPLICATION_JSON_TYPE));
+ }
+
+ @Test
public void primitive() {
final String val = client(MediaType.TEXT_PLAIN_TYPE).path("johnzon/primitive").get(String.class);
assertEquals("1986", val);
@@ -106,9 +127,10 @@ public class JohnzonProviderTest {
@Test
public void list() {
final ParameterizedType list = new ParameterizedType() {
+
@Override
public Type[] getActualTypeArguments() {
- return new Type[]{Johnzon.class};
+ return new Type[] { Johnzon.class };
}
@Override
@@ -146,12 +168,14 @@ public class JohnzonProviderTest {
}
private static WebClient client(final MediaType mediaType) {
- final WebClient client = WebClient.create(ENDPOINT_ADDRESS, singletonList(new JohnzonProvider<Object>())).accept(mediaType);
+ final WebClient client = WebClient.create(ENDPOINT_ADDRESS, singletonList(new JohnzonProvider<Object>()))
+ .accept(mediaType);
WebClient.getConfig(client).getRequestContext().put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
return client;
}
public static class Johnzon {
+
private String name;
public Johnzon(final String name) {
@@ -173,6 +197,7 @@ public class JohnzonProviderTest {
@Path("johnzon")
public static class JohnzonResource {
+
@GET
public Johnzon johnzon() {
return new Johnzon("johnzon");
@@ -207,6 +232,7 @@ public class JohnzonProviderTest {
@Path("stream")
public StreamingOutput out() {
return new StreamingOutput() {
+
@Override
public void write(OutputStream outputStream) throws IOException, WebApplicationException {
outputStream.write("ok".getBytes());
@@ -215,6 +241,18 @@ public class JohnzonProviderTest {
}
@GET
+ @Path("lazy_stream")
+ public void out(@Suspended final AsyncResponse response) {
+ response.resume(new StreamingOutput() {
+
+ @Override
+ public void write(OutputStream outputStream) throws IOException, WebApplicationException {
+ outputStream.write("ok".getBytes());
+ }
+ });
+ }
+
+ @GET
@Produces(MediaType.TEXT_PLAIN)
@Path("primitive")
public Integer primitive() {
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/pom.xml
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/pom.xml b/johnzon-jsonb/pom.xml
index 66d49f6..9b52c33 100644
--- a/johnzon-jsonb/pom.xml
+++ b/johnzon-jsonb/pom.xml
@@ -27,6 +27,7 @@
<artifactId>johnzon-jsonb</artifactId>
<name>Johnzon :: JSON-B Implementation</name>
+ <packaging>bundle</packaging>
<properties>
<java-compile.version>1.8</java-compile.version>
@@ -35,24 +36,33 @@
<dependencies>
<dependency>
- <groupId>javax.ws.rs</groupId>
- <artifactId>javax.ws.rs-api</artifactId>
- <version>2.0</version>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-annotation_1.2_spec</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jaxrs_2.0_spec</artifactId>
+ <version>1.0-alpha-1</version>
<scope>provided</scope>
+ <optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jcdi_1.1_spec</artifactId>
<version>1.0</version>
<scope>provided</scope>
+ <optional>true</optional>
</dependency>
-
<dependency>
- <groupId>org.apache.johnzon</groupId>
- <artifactId>jsonb-api</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jsonb_1.0_spec</artifactId>
+ <version>1.0</version>
<scope>provided</scope>
</dependency>
+
<dependency>
<groupId>org.apache.johnzon</groupId>
<artifactId>johnzon-mapper</artifactId>
@@ -96,5 +106,19 @@
<scope>test</scope>
</dependency>
</dependencies>
- <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Require-Capability>osgi.extender;filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
+ <Provide-Capability>osgi.serviceloader;osgi.serviceloader=javax.json.bind.spi.JsonbProvider</Provide-Capability>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
index 189dce4..25cf998 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
@@ -36,20 +36,34 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
+import java.io.StringReader;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.Properties;
+import java.util.function.Function;
+import java.util.logging.Logger;
+
+import javax.annotation.Priority;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Providers;
// here while we dont compile in java 8 jaxrs module, when migrated we'll merge it with IgnorableTypes hierarchy at least
@Provider
-@Produces("application/json")
-@Consumes("application/json")
-public class JsonbJaxrsProvider<T> implements MessageBodyWriter<T>, MessageBodyReader<T> {
- private final Collection<String> ignores;
- private final AtomicReference<Jsonb> delegate = new AtomicReference<>();
- private final JsonbConfig config = new JsonbConfig();
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@Priority(value = 4900)
+public class JsonbJaxrsProvider<T> implements MessageBodyWriter<T>, MessageBodyReader<T>, AutoCloseable {
+
+ protected final Collection<String> ignores;
+ protected final JsonbConfig config = new JsonbConfig();
+ protected volatile Function<Class<?>, Jsonb> delegate = null;
+ private boolean customized;
+
+ @Context
+ private Providers providers;
public JsonbJaxrsProvider() {
this(null);
@@ -59,41 +73,61 @@ public class JsonbJaxrsProvider<T> implements MessageBodyWriter<T>, MessageBodyR
this.ignores = ignores;
}
- protected Jsonb createJsonb() {
- return JsonbBuilder.create(config);
- }
-
private boolean isIgnored(final Class<?> type) {
return ignores != null && ignores.contains(type.getName());
}
// config - main containers support the configuration of providers this way
+ public void setFailOnUnknownProperties(final boolean active) {
+ config.setProperty("johnzon.fail-on-unknown-properties", active);
+ customized = true;
+ }
+
+ public void setOtherProperties(final String others) {
+ final Properties properties = new Properties() {{
+ try {
+ load(new StringReader(others));
+ } catch (final IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }};
+ properties.stringPropertyNames().forEach(k -> config.setProperty(k, properties.getProperty(k)));
+ customized = true;
+ }
+
public void setIJson(final boolean active) {
config.withStrictIJSON(active);
+ customized = true;
}
public void setEncoding(final String encoding) {
config.withEncoding(encoding);
+ customized = true;
}
public void setBinaryDataStrategy(final String binaryDataStrategy) {
config.withBinaryDataStrategy(binaryDataStrategy);
+ customized = true;
}
public void setPropertyNamingStrategy(final String propertyNamingStrategy) {
config.withPropertyNamingStrategy(propertyNamingStrategy);
+ customized = true;
}
public void setPropertyOrderStrategy(final String propertyOrderStrategy) {
config.withPropertyOrderStrategy(propertyOrderStrategy);
+ customized = true;
}
public void setNullValues(final boolean nulls) {
config.withNullValues(nulls);
+ customized = true;
}
public void setPretty(final boolean pretty) {
config.withFormatting(pretty);
+ customized = true;
}
// actual impl
@@ -101,21 +135,23 @@ public class JsonbJaxrsProvider<T> implements MessageBodyWriter<T>, MessageBodyR
@Override
public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
return !isIgnored(type)
- && InputStream.class != genericType && Reader.class != genericType && Response.class != genericType
- && String.class != genericType
- && !JsonStructure.class.isAssignableFrom(type);
+ && !InputStream.class.isAssignableFrom(type)
+ && !Reader.class.isAssignableFrom(type)
+ && !Response.class.isAssignableFrom(type)
+ && !CharSequence.class.isAssignableFrom(type)
+ && !JsonStructure.class.isAssignableFrom(type);
}
@Override
public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
return !isIgnored(type)
- && InputStream.class != genericType
- && OutputStream.class != genericType
- && Writer.class != genericType
- && StreamingOutput.class != genericType
- && String.class != genericType
- && Response.class != genericType
- && !JsonStructure.class.isAssignableFrom(type);
+ && !InputStream.class.isAssignableFrom(type)
+ && !OutputStream.class.isAssignableFrom(type)
+ && !Writer.class.isAssignableFrom(type)
+ && !StreamingOutput.class.isAssignableFrom(type)
+ && !CharSequence.class.isAssignableFrom(type)
+ && !Response.class.isAssignableFrom(type)
+ && !JsonStructure.class.isAssignableFrom(type);
}
@Override
@@ -125,26 +161,75 @@ public class JsonbJaxrsProvider<T> implements MessageBodyWriter<T>, MessageBodyR
@Override
public T readFrom(final Class<T> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType,
- final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream) throws IOException, WebApplicationException {
- return delegate().fromJson(entityStream, genericType);
+ final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream) throws IOException, WebApplicationException {
+ return getJsonb(type).fromJson(entityStream, genericType);
}
@Override
public void writeTo(final T t, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType,
- final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException, WebApplicationException {
- delegate().toJson(t, entityStream);
- }
-
- private Jsonb delegate() {
- Jsonb jsonb = delegate.get();
- if (jsonb == null) {
- final Jsonb newJsonb = createJsonb();
- if (delegate.compareAndSet(null, newJsonb)) {
- jsonb = newJsonb;
- } else {
- jsonb = delegate.get();
+ final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException, WebApplicationException {
+ getJsonb(type).toJson(t, entityStream);
+ }
+
+ protected Jsonb createJsonb() {
+ return JsonbBuilder.create(config);
+ }
+
+ protected Jsonb getJsonb(final Class<?> type) {
+ if (delegate == null){
+ synchronized (this) {
+ if (delegate == null) {
+ final ContextResolver<Jsonb> contextResolver = providers.getContextResolver(Jsonb.class, MediaType.APPLICATION_JSON_TYPE);
+ if (contextResolver != null) {
+ if (customized) {
+ Logger.getLogger(JsonbJaxrsProvider.class.getName())
+ .warning("Customizations done on the Jsonb instance will be ignored because a ContextResolver<Jsonb> was found");
+ }
+ delegate = new DynamicInstance(contextResolver); // faster than contextResolver::getContext
+ } else {
+ delegate = new ProvidedInstance(createJsonb()); // don't recreate it
+ }
+ }
}
}
- return jsonb;
+ return delegate.apply(type);
+ }
+
+ @Override
+ public synchronized void close() throws Exception {
+ if (AutoCloseable.class.isInstance(delegate)) {
+ AutoCloseable.class.cast(delegate).close();
+ }
+ }
+
+ private static final class DynamicInstance implements Function<Class<?>, Jsonb> {
+ private final ContextResolver<Jsonb> contextResolver;
+
+ private DynamicInstance(final ContextResolver<Jsonb> resolver) {
+ this.contextResolver = resolver;
+ }
+
+ @Override
+ public Jsonb apply(final Class<?> type) {
+ return contextResolver.getContext(type);
+ }
+ }
+
+ private static final class ProvidedInstance implements Function<Class<?>, Jsonb>, AutoCloseable {
+ private final Jsonb instance;
+
+ private ProvidedInstance(final Jsonb instance) {
+ this.instance = instance;
+ }
+
+ @Override
+ public Jsonb apply(final Class<?> aClass) {
+ return instance;
+ }
+
+ @Override
+ public void close() throws Exception {
+ instance.close();
+ }
}
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
deleted file mode 100644
index 7308374..0000000
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * 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.jsonb;
-
-import org.apache.johnzon.mapper.Mapper;
-import org.apache.johnzon.mapper.MapperException;
-import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType;
-
-import javax.json.bind.Jsonb;
-import javax.json.bind.JsonbException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.Writer;
-import java.lang.reflect.Array;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.Optional;
-import java.util.OptionalDouble;
-import java.util.OptionalInt;
-import java.util.OptionalLong;
-
-// TODO: Optional handling for lists (and arrays)?
-public class JohnsonJsonb implements Jsonb, AutoCloseable {
- private final Mapper delegate;
-
- public JohnsonJsonb(final Mapper build) {
- this.delegate = build;
- }
-
- @Override
- public <T> T fromJson(final String str, final Class<T> type) throws JsonbException {
- try {
- if (isArray(type)) {
- return delegate.readTypedArray(new StringReader(str), type.getComponentType(), type);
- } else if (Collection.class.isAssignableFrom(type)) {
- return (T) delegate.readCollection(new StringReader(str), new JohnzonParameterizedType(type, Object.class));
- }
- final Type mappingType = unwrapPrimitiveOptional(type);
- final Object object = delegate.readObject(str, mappingType);
- if (mappingType != type) {
- return wrapPrimitiveOptional(object, type);
- }
- return (T) object;
- } catch (final MapperException me) {
- throw new JsonbException(me.getMessage(), me);
- }
- }
-
- private <T> T wrapPrimitiveOptional(final Object object, final Type type) {
- if (OptionalDouble.class == type) {
- if (object == null) {
- return (T) OptionalDouble.empty();
- }
- return (T) OptionalDouble.of(Number.class.cast(object).doubleValue());
- } else if (OptionalInt.class == type) {
- if (object == null) {
- return (T) OptionalInt.empty();
- }
- return (T) OptionalInt.of(Number.class.cast(object).intValue());
- } else if (OptionalLong.class == type) {
- if (object == null) {
- return (T) OptionalLong.empty();
- }
- return (T) OptionalLong.of(Number.class.cast(object).longValue());
- }
- // Optional
- return (T) Optional.ofNullable(object);
- }
-
- private Type unwrapPrimitiveOptional(final Type type) {
- if (OptionalDouble.class == type) {
- return double.class;
- } else if (OptionalInt.class == type) {
- return int.class;
- } else if (OptionalLong.class == type) {
- return long.class;
- } else if (ParameterizedType.class.isInstance(type)) {
- final ParameterizedType pt = ParameterizedType.class.cast(type);
- if (Optional.class == pt.getRawType()) {
- return pt.getActualTypeArguments()[0];
- }
- }
- return type;
- }
-
- @Override
- public <T> T fromJson(final String str, final Type runtimeType) throws JsonbException {
- try {
- if (isArray(runtimeType)) {
- final Class cast = Class.class.cast(runtimeType);
- return (T) delegate.readTypedArray(new StringReader(str), cast.getComponentType(), cast);
- } else if (isCollection(runtimeType)) {
- return (T) delegate.readCollection(new StringReader(str), ParameterizedType.class.cast(runtimeType));
- }
- final Type mappingType = unwrapPrimitiveOptional(runtimeType);
- final Object object = delegate.readObject(str, mappingType);
- if (mappingType != runtimeType) {
- return wrapPrimitiveOptional(object, runtimeType);
- }
- return (T) object;
- } catch (final MapperException me) {
- throw new JsonbException(me.getMessage(), me);
- }
- }
-
- @Override
- public <T> T fromJson(final Reader reader, final Class<T> type) throws JsonbException {
- try {
- if (isArray(type)) {
- return delegate.readTypedArray(reader, type.getComponentType(), type);
- } else if (Collection.class.isAssignableFrom(type)) {
- return (T) delegate.readCollection(reader, new JohnzonParameterizedType(type, Object.class));
- }
- final Type mappingType = unwrapPrimitiveOptional(type);
- final Object object = delegate.readObject(reader, mappingType);
- if (mappingType != type) {
- return wrapPrimitiveOptional(object, type);
- }
- return (T) object;
- } catch (final MapperException me) {
- throw new JsonbException(me.getMessage(), me);
- }
- }
-
- @Override
- public <T> T fromJson(final Reader reader, final Type runtimeType) throws JsonbException {
- try {
- if (isArray(runtimeType)) {
- final Class<T> type = Class.class.cast(runtimeType);
- return delegate.readTypedArray(reader, type.getComponentType(), type);
- } else if (isCollection(runtimeType)) {
- return (T) delegate.readCollection(reader, ParameterizedType.class.cast(runtimeType));
- }
- final Type mappingType = unwrapPrimitiveOptional(runtimeType);
- final Object object = delegate.readObject(reader, mappingType);
- if (mappingType != runtimeType) {
- return wrapPrimitiveOptional(object, runtimeType);
- }
- return (T) object;
- } catch (final MapperException me) {
- throw new JsonbException(me.getMessage(), me);
- }
- }
-
- @Override
- public <T> T fromJson(final InputStream stream, final Class<T> type) throws JsonbException {
- try {
- if (isArray(type)) {
- return delegate.readTypedArray(stream, type.getComponentType(), type);
- } else if (Collection.class.isAssignableFrom(type)) {
- return (T) delegate.readCollection(stream, new JohnzonParameterizedType(type, Object.class));
- }
- final Type mappingType = unwrapPrimitiveOptional(type);
- final Object object = delegate.readObject(stream, mappingType);
- if (mappingType != type) {
- return wrapPrimitiveOptional(object, type);
- }
- return (T) object;
- } catch (final MapperException me) {
- throw new JsonbException(me.getMessage(), me);
- }
- }
-
- @Override
- public <T> T fromJson(final InputStream stream, final Type runtimeType) throws JsonbException {
- try {
- if (isArray(runtimeType)) {
- final Class<T> type = Class.class.cast(runtimeType);
- return delegate.readTypedArray(stream, type.getComponentType(), type);
- } else if (isCollection(runtimeType)) {
- return (T) delegate.readCollection(stream, ParameterizedType.class.cast(runtimeType));
- }
-
- final Type mappingType = unwrapPrimitiveOptional(runtimeType);
- final Object object = delegate.readObject(stream, mappingType);
- if (mappingType != runtimeType) {
- return wrapPrimitiveOptional(object, runtimeType);
- }
- return (T) object;
- } catch (final MapperException me) {
- throw new JsonbException(me.getMessage(), me);
- }
- }
-
- @Override
- public String toJson(final Object inObject) throws JsonbException {
- try {
- final Object object = unwrapOptional(inObject);
- if (object == null) {
- return "null";
- }
- if (isArray(object.getClass())) {
- return delegate.writeArrayAsString(toArray(object));
- } else if (Collection.class.isInstance(object)) {
- return delegate.writeArrayAsString(Collection.class.cast(object));
- }
- return delegate.writeObjectAsString(object);
-
- } catch (final MapperException me) {
- throw new JsonbException(me.getMessage(), me);
- }
- }
-
- private Object[] toArray(final Object object) {
- final Class<?> componentType = object.getClass().getComponentType();
- Object[] array;
- if (int.class == componentType) {
- final int length = Array.getLength(object);
- array = new Integer[length];
- for (int i = 0; i < length; i++) {
- array[i] = Array.getInt(object, i);
- }
- } else if (double.class == componentType) {
- final int length = Array.getLength(object);
- array = new Integer[length];
- for (int i = 0; i < length; i++) {
- array[i] = Array.getDouble(object, i);
- }
- } else if (byte.class == componentType) {
- final int length = Array.getLength(object);
- array = new Integer[length];
- for (int i = 0; i < length; i++) {
- array[i] = Array.getByte(object, i);
- }
- } else if (char.class == componentType) {
- final int length = Array.getLength(object);
- array = new Integer[length];
- for (int i = 0; i < length; i++) {
- array[i] = Array.getChar(object, i);
- }
- } else if (float.class == componentType) {
- final int length = Array.getLength(object);
- array = new Integer[length];
- for (int i = 0; i < length; i++) {
- array[i] = Array.getFloat(object, i);
- }
- } else if (long.class == componentType) {
- final int length = Array.getLength(object);
- array = new Integer[length];
- for (int i = 0; i < length; i++) {
- array[i] = Array.getLong(object, i);
- }
- } else if (short.class == componentType) {
- final int length = Array.getLength(object);
- array = new Integer[length];
- for (int i = 0; i < length; i++) {
- array[i] = Array.getShort(object, i);
- }
- } else {
- array = (Object[]) object;
- }
- return array;
- }
-
- @Override
- public String toJson(final Object inObject, final Type runtimeType) throws JsonbException {
- final Object object = unwrapOptional(inObject);
- if (object != null && isArray(runtimeType)) {
- return delegate.writeArrayAsString((Object[]) object);
- } else if (isCollection(runtimeType)) {
- return delegate.writeArrayAsString(Collection.class.cast(object));
- }
- return delegate.writeObjectAsString(object);
- }
-
- @Override
- public void toJson(final Object inObject, final Writer writer) throws JsonbException {
- final Object object = unwrapOptional(inObject);
- if (object != null && isArray(object.getClass())) {
- delegate.writeArray((Object[]) object, writer);
- } else if (Collection.class.isInstance(object)) {
- delegate.writeArray(Collection.class.cast(object), writer);
- } else {
- delegate.writeObject(object, writer);
- }
- }
-
- @Override
- public void toJson(final Object inObject, final Type runtimeType, final Writer writer) throws JsonbException {
- final Object object = unwrapOptional(inObject);
- if (object != null && isArray(runtimeType)) {
- delegate.writeArray((Object[]) object, writer);
- } else if (isCollection(runtimeType)) {
- delegate.writeArray(Collection.class.cast(object), writer);
- } else {
- delegate.writeObject(object, writer);
- }
- }
-
- @Override
- public void toJson(final Object inObject, final OutputStream stream) throws JsonbException {
- final Object object = unwrapOptional(inObject);
- if (object != null && isArray(object.getClass())) {
- delegate.writeArray((Object[]) object, stream);
- } else if (Collection.class.isInstance(object)) {
- delegate.writeArray(Collection.class.cast(object), stream);
- } else {
- delegate.writeObject(object, stream);
- }
- }
-
- @Override
- public void toJson(final Object inObject, final Type runtimeType, final OutputStream stream) throws JsonbException {
- final Object object = unwrapOptional(inObject);
- if (object != null && isArray(runtimeType)) {
- delegate.writeArray((Object[]) object, stream);
- } else if (isCollection(runtimeType)) {
- delegate.writeArray(Collection.class.cast(object), stream);
- } else {
- delegate.writeObject(object, stream);
- }
- }
-
- private Object unwrapOptional(final Object inObject) {
- if (Optional.class.isInstance(inObject)) {
- return Optional.class.cast(inObject).orElse(null);
- }
- if (OptionalInt.class.isInstance(inObject)) {
- final OptionalInt optionalInt = OptionalInt.class.cast(inObject);
- return optionalInt.isPresent() ? optionalInt.getAsInt() : null;
- }
- if (OptionalLong.class.isInstance(inObject)) {
- final OptionalLong optionalLong = OptionalLong.class.cast(inObject);
- return optionalLong.isPresent() ? optionalLong.getAsLong() : null;
- }
- if (OptionalDouble.class.isInstance(inObject)) {
- final OptionalDouble optionalDouble = OptionalDouble.class.cast(inObject);
- return optionalDouble.isPresent() ? optionalDouble.getAsDouble() : null;
- }
- return inObject;
- }
-
- private boolean isArray(final Type runtimeType) {
- return Class.class.isInstance(runtimeType) && Class.class.cast(runtimeType).isArray();
- }
-
- private boolean isCollection(final Type runtimeType) {
- if (!ParameterizedType.class.isInstance(runtimeType)) {
- return false;
- }
- final Type rawType = ParameterizedType.class.cast(runtimeType).getRawType();
- return Class.class.isInstance(rawType) && Collection.class.isAssignableFrom(Class.class.cast(rawType));
- }
-
- @Override
- public void close() {
- delegate.close();
- }
-}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index 137cf4c..40ec155 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -20,6 +20,7 @@ package org.apache.johnzon.jsonb;
import org.apache.johnzon.core.AbstractJsonFactory;
import org.apache.johnzon.core.JsonGeneratorFactoryImpl;
+import org.apache.johnzon.core.JsonParserFactoryImpl;
import org.apache.johnzon.jsonb.cdi.CDIs;
import org.apache.johnzon.jsonb.converter.JohnzonJsonbAdapter;
import org.apache.johnzon.jsonb.factory.SimpleJohnzonAdapterFactory;
@@ -31,6 +32,9 @@ import org.apache.johnzon.mapper.Converter;
import org.apache.johnzon.mapper.Mapper;
import org.apache.johnzon.mapper.MapperBuilder;
import org.apache.johnzon.mapper.ObjectConverter;
+import org.apache.johnzon.mapper.SerializeValueFilter;
+import org.apache.johnzon.mapper.access.AccessMode;
+import org.apache.johnzon.mapper.access.FieldAndMethodAccessMode;
import org.apache.johnzon.mapper.internal.AdapterKey;
import org.apache.johnzon.mapper.internal.ConverterAdapter;
@@ -48,7 +52,9 @@ import javax.json.bind.serializer.JsonbSerializer;
import javax.json.spi.JsonProvider;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParserFactory;
+import java.io.Closeable;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
@@ -84,8 +90,19 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
import static java.time.format.DateTimeFormatter.ofPattern;
+import static java.time.temporal.ChronoField.DAY_OF_MONTH;
+import static java.time.temporal.ChronoField.HOUR_OF_DAY;
+import static java.time.temporal.ChronoField.MILLI_OF_SECOND;
+import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
+import static java.time.temporal.ChronoField.YEAR;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalQueries;
import static java.util.Collections.emptyMap;
+import java.util.Objects;
import static java.util.Optional.ofNullable;
+import java.util.concurrent.TimeUnit;
import static javax.json.bind.config.PropertyNamingStrategy.IDENTITY;
import static javax.json.bind.config.PropertyOrderStrategy.LEXICOGRAPHICAL;
@@ -114,27 +131,9 @@ public class JohnzonBuilder implements JsonbBuilder {
public Jsonb build() {
if (jsonp != null) {
builder.setGeneratorFactory(jsonp.createGeneratorFactory(generatorConfig()));
- builder.setReaderFactory(jsonp.createReaderFactory(emptyMap()));
+ builder.setReaderFactory(jsonp.createReaderFactory(readerConfig()));
}
- final Supplier<JsonParserFactory> parserFactoryProvider = new Supplier<JsonParserFactory>() { // thread safety is not mandatory
- private final AtomicReference<JsonParserFactory> ref = new AtomicReference<>();
-
- @Override
- public JsonParserFactory get() {
- JsonParserFactory factory = ref.get();
- if (factory == null) {
- factory = doCreate();
- if (!ref.compareAndSet(null, factory)) {
- factory = ref.get();
- }
- }
- return factory;
- }
-
- private JsonParserFactory doCreate() {
- return (jsonp == null ? JsonProvider.provider() : jsonp).createParserFactory(emptyMap());
- }
- };
+ final Supplier<JsonParserFactory> parserFactoryProvider = createJsonParserFactory();
if (config == null) {
config = new JsonbConfig();
@@ -207,6 +206,12 @@ public class JohnzonBuilder implements JsonbBuilder {
config.getProperty("johnzon.primitiveConverters")
.map(v -> !Boolean.class.isInstance(v) ? Boolean.parseBoolean(v.toString()) : Boolean.class.cast(v))
.ifPresent(builder::setPrimitiveConverters);
+ config.getProperty("johnzon.useBigDecimalForFloats")
+ .map(v -> !Boolean.class.isInstance(v) ? Boolean.parseBoolean(v.toString()) : Boolean.class.cast(v))
+ .ifPresent(builder::setUseBigDecimalForFloats);
+ config.getProperty("johnzon.deduplicateObjects")
+ .map(v -> !Boolean.class.isInstance(v) ? Boolean.parseBoolean(v.toString()) : Boolean.class.cast(v))
+ .ifPresent(builder::setDeduplicateObjects);
final Map<AdapterKey, Adapter<?, ?>> defaultConverters = createJava8Converters(builder);
@@ -230,11 +235,16 @@ public class JohnzonBuilder implements JsonbBuilder {
}
throw new IllegalArgumentException("Unsupported factory: " + val);
}).orElseGet(this::findFactory);
- final JsonbAccessMode accessMode = new JsonbAccessMode(
- propertyNamingStrategy, orderValue, visibilityStrategy,
- !namingStrategyValue.orElse("").equals(PropertyNamingStrategy.CASE_INSENSITIVE),
- defaultConverters,
- factory, parserFactoryProvider);
+ final AccessMode accessMode = config.getProperty("johnzon.accessMode")
+ .map(this::toAccessMode)
+ .orElseGet(() -> new JsonbAccessMode(
+ propertyNamingStrategy, orderValue, visibilityStrategy,
+ !namingStrategyValue.orElse("").equals(PropertyNamingStrategy.CASE_INSENSITIVE),
+ defaultConverters,
+ factory, parserFactoryProvider,
+ config.getProperty("johnzon.accessModeDelegate")
+ .map(this::toAccessMode)
+ .orElseGet(() -> new FieldAndMethodAccessMode(true, true, false))));
builder.setAccessMode(accessMode);
@@ -253,6 +263,9 @@ public class JohnzonBuilder implements JsonbBuilder {
config.getProperty(JsonbConfig.STRICT_IJSON).map(Boolean.class::cast).ifPresent(ijson -> {
// no-op: https://tools.ietf.org/html/rfc7493 the only MUST of the spec should be fine by default
});
+ config.getProperty("johnzon.fail-on-unknown-properties")
+ .map(v -> Boolean.class.isInstance(v) ? Boolean.class.cast(v) : Boolean.parseBoolean(String.valueOf(v)))
+ .ifPresent(builder::setFailOnUnknownProperties);
config.getProperty(JsonbConfig.BINARY_DATA_STRATEGY).map(String.class::cast).ifPresent(bin -> {
switch (bin) {
@@ -284,6 +297,23 @@ public class JohnzonBuilder implements JsonbBuilder {
builder.setReadAttributeBeforeWrite(
config.getProperty("johnzon.readAttributeBeforeWrite").map(Boolean.class::cast).orElse(false));
+ builder.setAutoAdjustStringBuffers(
+ config.getProperty("johnzon.autoAdjustBuffer").map(Boolean.class::cast).orElse(true));
+ config.getProperty("johnzon.serialize-value-filter")
+ .map(s -> {
+ if (String.class.isInstance(s)) {
+ try {
+ return SerializeValueFilter.class.cast(
+ Thread.currentThread().getContextClassLoader().loadClass(s.toString()).getConstructor().newInstance());
+ } catch (final InstantiationException | IllegalAccessException | NoSuchMethodException | ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalArgumentException(e.getCause());
+ }
+ }
+ return s;
+ })
+ .ifPresent(s -> builder.setSerializeValueFilter(SerializeValueFilter.class.cast(s)));
config.getProperty(JsonbConfig.SERIALIZERS).map(JsonbSerializer[].class::cast).ifPresent(serializers -> {
Stream.of(serializers).forEach(s -> {
@@ -298,7 +328,7 @@ public class JohnzonBuilder implements JsonbBuilder {
}
builder.addObjectConverter(
Class.class.cast(args[0]), (ObjectConverter.Writer)
- (instance, jsonbGenerator) -> s.serialize(instance, jsonbGenerator.getJsonGenerator(), new JohnzonSerializationContext(jsonbGenerator)));
+ (instance, jsonbGenerator) -> s.serialize(instance, jsonbGenerator.getJsonGenerator(), new JohnzonSerializationContext(jsonbGenerator)));
});
});
config.getProperty(JsonbConfig.DESERIALIZERS).map(JsonbDeserializer[].class::cast).ifPresent(deserializers -> {
@@ -314,15 +344,18 @@ public class JohnzonBuilder implements JsonbBuilder {
// TODO: support PT in ObjectConverter (list)
builder.addObjectConverter(
Class.class.cast(args[0]), (ObjectConverter.Reader)
- (jsonObject, targetType, parser) -> d.deserialize(
- parserFactoryProvider.get().createParser(jsonObject), new JohnzonDeserializationContext(parser), targetType));
+ (jsonObject, targetType, parser) -> d.deserialize(
+ parserFactoryProvider.get().createParser(jsonObject), new JohnzonDeserializationContext(parser), targetType));
});
});
final boolean useCdi = cdiIntegration != null && cdiIntegration.isCanWrite() && config.getProperty("johnzon.cdi.activated").map(Boolean.class::cast).orElse(Boolean.TRUE);
- final Mapper mapper = builder.addCloseable(accessMode).build();
+ if (Closeable.class.isInstance(accessMode)) {
+ builder.addCloseable(Closeable.class.cast(accessMode));
+ }
+ final Mapper mapper = builder.build();
- return useCdi ? new JohnsonJsonb(mapper) {
+ return useCdi ? new JohnzonJsonb(mapper) {
{
cdiIntegration.track(this);
}
@@ -337,14 +370,50 @@ public class JohnzonBuilder implements JsonbBuilder {
}
}
}
- } : new JohnsonJsonb(mapper);
+ } : new JohnzonJsonb(mapper);
+ }
+
+ private AccessMode toAccessMode(final Object s) {
+ if (String.class.isInstance(s)) {
+ try {
+ return AccessMode.class.cast(
+ Thread.currentThread().getContextClassLoader().loadClass(s.toString()).getConstructor().newInstance());
+ } catch (final InstantiationException | IllegalAccessException | NoSuchMethodException | ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalArgumentException(e.getCause());
+ }
+ }
+ return AccessMode.class.cast(s);
+ }
+
+ private Supplier<JsonParserFactory> createJsonParserFactory() {
+ return new Supplier<JsonParserFactory>() { // thread safety is not mandatory
+ private final AtomicReference<JsonParserFactory> ref = new AtomicReference<>();
+
+ @Override
+ public JsonParserFactory get() {
+ JsonParserFactory factory = ref.get();
+ if (factory == null) {
+ factory = doCreate();
+ if (!ref.compareAndSet(null, factory)) {
+ factory = ref.get();
+ }
+ }
+ return factory;
+ }
+
+ private JsonParserFactory doCreate() {
+ return (jsonp == null ? JsonProvider.provider() : jsonp).createParserFactory(emptyMap());
+ }
+ };
}
private ParameterizedType findPT(final Object s, final Class<?> type) {
return ParameterizedType.class.cast(
- Stream.of(s.getClass().getGenericInterfaces())
- .filter(i -> ParameterizedType.class.isInstance(i) && ParameterizedType.class.cast(i).getRawType() == type)
- .findFirst().orElse(null));
+ Stream.of(s.getClass().getGenericInterfaces())
+ .filter(i -> ParameterizedType.class.isInstance(i) && ParameterizedType.class.cast(i).getRawType() == type)
+ .findFirst().orElse(null));
}
private Object getBeanManager() {
@@ -572,98 +641,151 @@ public class JohnzonBuilder implements JsonbBuilder {
final Optional<Locale> locale = config.getProperty(JsonbConfig.LOCALE).map(Locale.class::cast);
final DateTimeFormatter formatter = locale.isPresent() ? ofPattern(dateFormat, locale.get()) : ofPattern(dateFormat);
- // Note: we try and fallback in the parsing cause we don't know if the date format provided is
- // for date, datetime, time
-
converters.put(new AdapterKey(Date.class, String.class), new ConverterAdapter<>(new Converter<Date>() {
- private volatile boolean useFormatter = true;
@Override
public String toString(final Date instance) {
- return LocalDateTime.ofInstant(instance.toInstant(), zoneIDUTC).toString();
+ return formatter.format(ZonedDateTime.ofInstant(instance.toInstant(), zoneIDUTC));
}
@Override
public Date fromString(final String text) {
- if (useFormatter) {
- try {
- return Date.from(LocalDateTime.parse(text, formatter).toInstant(ZoneOffset.UTC));
- } catch (final DateTimeParseException dpe) {
- useFormatter = false;
- }
+ try {
+ return Date.from(parseZonedDateTime(text, formatter, zoneIDUTC).toInstant());
+ } catch (final DateTimeParseException dpe) {
+ return Date.from(LocalDateTime.parse(text).toInstant(ZoneOffset.UTC));
}
- return Date.from(LocalDateTime.parse(text).toInstant(ZoneOffset.UTC));
}
}));
converters.put(new AdapterKey(LocalDateTime.class, String.class), new ConverterAdapter<>(new Converter<LocalDateTime>() {
- private volatile boolean useFormatter = true;
@Override
public String toString(final LocalDateTime instance) {
- return instance.toString();
+ return formatter.format(ZonedDateTime.ofInstant(instance.toInstant(ZoneOffset.UTC), zoneIDUTC));
}
@Override
public LocalDateTime fromString(final String text) {
- if (useFormatter) {
- try {
- return LocalDateTime.parse(text, formatter);
- } catch (final DateTimeParseException dpe) {
- useFormatter = false;
- }
+ try {
+ return parseZonedDateTime(text, formatter, zoneIDUTC).toLocalDateTime();
+ } catch (final DateTimeParseException dpe) {
+ return LocalDateTime.parse(text);
}
- return LocalDateTime.parse(text);
}
}));
converters.put(new AdapterKey(LocalDate.class, String.class), new ConverterAdapter<>(new Converter<LocalDate>() {
- private volatile boolean useFormatter = true;
@Override
public String toString(final LocalDate instance) {
- return instance.toString();
+ return formatter.format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(TimeUnit.DAYS.toMillis(instance.toEpochDay())), zoneIDUTC));
}
@Override
public LocalDate fromString(final String text) {
- if (useFormatter) {
- try {
- return LocalDate.parse(text, formatter);
- } catch (final DateTimeParseException dpe) {
- useFormatter = false;
- }
+ try {
+ return parseZonedDateTime(text, formatter, zoneIDUTC).toLocalDate();
+ } catch (final DateTimeParseException dpe) {
+ return LocalDate.parse(text);
+ }
+ }
+ }));
+ converters.put(new AdapterKey(OffsetDateTime.class, String.class), new ConverterAdapter<>(new Converter<OffsetDateTime>() {
+
+ @Override
+ public String toString(final OffsetDateTime instance) {
+ return formatter.format(ZonedDateTime.ofInstant(instance.toInstant(), zoneIDUTC));
+ }
+
+ @Override
+ public OffsetDateTime fromString(final String text) {
+ try {
+ return parseZonedDateTime(text, formatter, zoneIDUTC).toOffsetDateTime();
+ } catch (final DateTimeParseException dpe) {
+ return OffsetDateTime.parse(text);
}
- return LocalDate.parse(text);
}
}));
converters.put(new AdapterKey(ZonedDateTime.class, String.class), new ConverterAdapter<>(new Converter<ZonedDateTime>() {
- private volatile boolean useFormatter = true;
@Override
public String toString(final ZonedDateTime instance) {
- return instance.toString();
+ return formatter.format(ZonedDateTime.ofInstant(instance.toInstant(), zoneIDUTC));
}
@Override
public ZonedDateTime fromString(final String text) {
- if (useFormatter) {
- try {
- return ZonedDateTime.parse(text, formatter);
- } catch (final DateTimeParseException dpe) {
- useFormatter = false;
- }
+ try {
+ return parseZonedDateTime(text, formatter, zoneIDUTC);
+ } catch (final DateTimeParseException dpe) {
+ return ZonedDateTime.parse(text);
}
- return ZonedDateTime.parse(text);
+ }
+ }));
+ converters.put(new AdapterKey(Calendar.class, String.class), new ConverterAdapter<>(new Converter<Calendar>() {
+
+ @Override
+ public String toString(final Calendar instance) {
+ return formatter.format(ZonedDateTime.ofInstant(instance.toInstant(), zoneIDUTC));
+ }
+
+ @Override
+ public Calendar fromString(final String text) {
+ Calendar instance = Calendar.getInstance();
+ instance.setTime(Date.from(parseZonedDateTime(text, formatter, zoneIDUTC).toInstant()));
+ return instance;
+ }
+ }));
+ converters.put(new AdapterKey(GregorianCalendar.class, String.class), new ConverterAdapter<>(new Converter<GregorianCalendar>() {
+
+ @Override
+ public String toString(final GregorianCalendar instance) {
+ return formatter.format(ZonedDateTime.ofInstant(instance.toInstant(), zoneIDUTC));
+ }
+
+ @Override
+ public GregorianCalendar fromString(final String text) {
+ Calendar instance = GregorianCalendar.getInstance();
+ instance.setTime(Date.from(parseZonedDateTime(text, formatter, zoneIDUTC).toInstant()));
+ return GregorianCalendar.class.cast(instance);
+ }
+ }));
+ converters.put(new AdapterKey(Instant.class, String.class), new ConverterAdapter<>(new Converter<Instant>() {
+
+ @Override
+ public String toString(final Instant instance) {
+ return formatter.format(ZonedDateTime.ofInstant(instance, zoneIDUTC));
+ }
+
+ @Override
+ public Instant fromString(final String text) {
+ return parseZonedDateTime(text, formatter, zoneIDUTC).toInstant();
}
}));
});
}
+
+ private static ZonedDateTime parseZonedDateTime(final String text, final DateTimeFormatter formatter, final ZoneId defaultZone){
+ TemporalAccessor parse = formatter.parse(text);
+ ZoneId zone = parse.query(TemporalQueries.zone());
+ if (Objects.isNull(zone)) {
+ zone = defaultZone;
+ }
+ int year = parse.isSupported(YEAR) ? parse.get(YEAR) : 0;
+ int month = parse.isSupported(MONTH_OF_YEAR) ? parse.get(MONTH_OF_YEAR) : 0;
+ int day = parse.isSupported(DAY_OF_MONTH) ? parse.get(DAY_OF_MONTH) : 0;
+ int hour = parse.isSupported(HOUR_OF_DAY) ? parse.get(HOUR_OF_DAY) : 0;
+ int minute = parse.isSupported(MINUTE_OF_HOUR) ? parse.get(MINUTE_OF_HOUR) : 0;
+ int second = parse.isSupported(SECOND_OF_MINUTE) ? parse.get(SECOND_OF_MINUTE) : 0;
+ int millisecond = parse.isSupported(MILLI_OF_SECOND) ? parse.get(MILLI_OF_SECOND) : 0;
+ return ZonedDateTime.of(year, month, day, hour, minute, second, millisecond, zone);
+ }
private static void logIfDeprecatedTimeZone(final String text) {
/* TODO: get the list, UTC is clearly not deprecated but uses 3 letters
if (text.length() == 3) { // don't fail but log it
Logger.getLogger(JohnzonBuilder.class.getName()).severe("Deprecated timezone: " + text);
}
- */
+ */
}
private Map<String, ?> generatorConfig() {
@@ -676,4 +798,16 @@ public class JohnzonBuilder implements JsonbBuilder {
config.getProperty(JsonbConfig.FORMATTING).ifPresent(b -> map.put(JsonGenerator.PRETTY_PRINTING, b));
return map;
}
+
+ private Map<String, ?> readerConfig() {
+ final Map<String, Object> map = new HashMap<>();
+ if (config == null) {
+ return map;
+ }
+ config.getProperty(JsonParserFactoryImpl.BUFFER_LENGTH).ifPresent(b -> map.put(JsonParserFactoryImpl.BUFFER_LENGTH, b));
+ config.getProperty(JsonParserFactoryImpl.MAX_STRING_LENGTH).ifPresent(b -> map.put(JsonParserFactoryImpl.MAX_STRING_LENGTH, b));
+ config.getProperty(JsonParserFactoryImpl.SUPPORTS_COMMENTS).ifPresent(b -> map.put(JsonParserFactoryImpl.SUPPORTS_COMMENTS, b));
+ config.getProperty(AbstractJsonFactory.BUFFER_STRATEGY).ifPresent(b -> map.put(AbstractJsonFactory.BUFFER_STRATEGY, b));
+ return map;
+ }
}