diff --git a/blackbox-test/src/main/java/org/example/customer/customtype/CustomTypeComponent.java b/blackbox-test/src/main/java/org/example/customer/customtype/CustomTypeComponent.java index b5c48bac..0db9c1d9 100644 --- a/blackbox-test/src/main/java/org/example/customer/customtype/CustomTypeComponent.java +++ b/blackbox-test/src/main/java/org/example/customer/customtype/CustomTypeComponent.java @@ -1,9 +1,9 @@ package org.example.customer.customtype; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; import io.avaje.jsonb.spi.JsonbComponent; import io.avaje.spi.ServiceProvider; diff --git a/blackbox-test/src/main/java/org/example/other/custom/CustomClassJsonAdapter.java b/blackbox-test/src/main/java/org/example/other/custom/CustomClassJsonAdapter.java index 1aea49ee..7eb09092 100644 --- a/blackbox-test/src/main/java/org/example/other/custom/CustomClassJsonAdapter.java +++ b/blackbox-test/src/main/java/org/example/other/custom/CustomClassJsonAdapter.java @@ -1,11 +1,11 @@ package org.example.other.custom; +import io.avaje.json.JsonAdapter; import io.avaje.jsonb.CustomAdapter; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.json.PropertyNames; @CustomAdapter public class CustomClassJsonAdapter implements JsonAdapter { diff --git a/blackbox-test/src/main/java/org/example/other/custom/CustomEntryJsonAdapter.java b/blackbox-test/src/main/java/org/example/other/custom/CustomEntryJsonAdapter.java index acce5d2b..1d7cd4f7 100644 --- a/blackbox-test/src/main/java/org/example/other/custom/CustomEntryJsonAdapter.java +++ b/blackbox-test/src/main/java/org/example/other/custom/CustomEntryJsonAdapter.java @@ -4,13 +4,8 @@ import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Map.Entry; -import io.avaje.jsonb.CustomAdapter; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.Jsonb; -import io.avaje.jsonb.Types; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.jsonb.*; +import io.avaje.json.*; @CustomAdapter public class CustomEntryJsonAdapter implements JsonAdapter> { @@ -19,10 +14,9 @@ public class CustomEntryJsonAdapter implements JsonAdapter> { private final JsonAdapter generic2; private final PropertyNames names; - public static final JsonAdapter.Factory FACTORY = + public static final AdapterFactory FACTORY = (type, jsonb) -> { if (Types.isGenericTypeOf(type, Entry.class)) { - return new CustomEntryJsonAdapter<>(jsonb, Types.typeArguments(type)); } return null; diff --git a/blackbox-test/src/main/java/org/example/other/custom/serializer/MoneySerializer.java b/blackbox-test/src/main/java/org/example/other/custom/serializer/MoneySerializer.java index 4d680f34..bea8a520 100644 --- a/blackbox-test/src/main/java/org/example/other/custom/serializer/MoneySerializer.java +++ b/blackbox-test/src/main/java/org/example/other/custom/serializer/MoneySerializer.java @@ -3,10 +3,10 @@ import java.math.BigDecimal; import java.math.RoundingMode; +import io.avaje.json.JsonAdapter; import io.avaje.jsonb.CustomAdapter; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; @CustomAdapter(global = false) diff --git a/blackbox-test/src/test/java/org/example/customer/CustomerTest.java b/blackbox-test/src/test/java/org/example/customer/CustomerTest.java index 68f107e7..6e06d4b3 100644 --- a/blackbox-test/src/test/java/org/example/customer/CustomerTest.java +++ b/blackbox-test/src/test/java/org/example/customer/CustomerTest.java @@ -1,5 +1,6 @@ package org.example.customer; +import io.avaje.json.*; import io.avaje.jsonb.*; import org.junit.jupiter.api.Test; diff --git a/blackbox-test/src/test/java/org/example/customer/IErrOnReadTest.java b/blackbox-test/src/test/java/org/example/customer/IErrOnReadTest.java index 5a9d05b2..81c96c71 100644 --- a/blackbox-test/src/test/java/org/example/customer/IErrOnReadTest.java +++ b/blackbox-test/src/test/java/org/example/customer/IErrOnReadTest.java @@ -1,8 +1,7 @@ package org.example.customer; -import io.avaje.jsonb.JsonException; -import io.avaje.jsonb.JsonType; -import io.avaje.jsonb.Jsonb; +import io.avaje.json.*; +import io.avaje.jsonb.*; import org.junit.jupiter.api.Test; import java.io.ByteArrayOutputStream; diff --git a/blackbox-test/src/test/java/org/example/customer/SomeAddressWrapperTest.java b/blackbox-test/src/test/java/org/example/customer/SomeAddressWrapperTest.java index 6b27179c..ba326ed4 100644 --- a/blackbox-test/src/test/java/org/example/customer/SomeAddressWrapperTest.java +++ b/blackbox-test/src/test/java/org/example/customer/SomeAddressWrapperTest.java @@ -1,6 +1,6 @@ package org.example.customer; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; import org.junit.jupiter.api.Test; diff --git a/blackbox-test/src/test/java/org/example/customer/customtype/CustomScalarTypeTest.java b/blackbox-test/src/test/java/org/example/customer/customtype/CustomScalarTypeTest.java index 61260488..c810f65f 100644 --- a/blackbox-test/src/test/java/org/example/customer/customtype/CustomScalarTypeTest.java +++ b/blackbox-test/src/test/java/org/example/customer/customtype/CustomScalarTypeTest.java @@ -1,9 +1,7 @@ package org.example.customer.customtype; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.Jsonb; +import io.avaje.json.*; +import io.avaje.jsonb.*; import org.junit.jupiter.api.Test; import java.nio.charset.StandardCharsets; diff --git a/blackbox-test/src/test/java/org/example/customer/optional/OptionalCustomerTest.java b/blackbox-test/src/test/java/org/example/customer/optional/OptionalCustomerTest.java index 818a2b71..8699a54b 100644 --- a/blackbox-test/src/test/java/org/example/customer/optional/OptionalCustomerTest.java +++ b/blackbox-test/src/test/java/org/example/customer/optional/OptionalCustomerTest.java @@ -15,11 +15,8 @@ import org.example.customer.Customer; import org.junit.jupiter.api.Test; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonType; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.Jsonb; -import io.avaje.jsonb.Types; +import io.avaje.json.*; +import io.avaje.jsonb.*; class OptionalCustomerTest { diff --git a/blackbox-test/src/test/java/org/example/customer/skip/MyCustomerTest.java b/blackbox-test/src/test/java/org/example/customer/skip/MyCustomerTest.java index c5dadb4a..b4343230 100644 --- a/blackbox-test/src/test/java/org/example/customer/skip/MyCustomerTest.java +++ b/blackbox-test/src/test/java/org/example/customer/skip/MyCustomerTest.java @@ -2,7 +2,7 @@ import io.avaje.jsonb.JsonType; import io.avaje.jsonb.Jsonb; -import io.avaje.jsonb.stream.JsonStream; +import io.avaje.json.stream.JsonStream; import org.junit.jupiter.api.Test; import java.nio.charset.StandardCharsets; @@ -16,7 +16,7 @@ class MyCustomerTest { @Test void toJson_fromJson() { - Jsonb jsonb = Jsonb.builder().adapter(new JsonStream()).build(); + Jsonb jsonb = Jsonb.builder().adapter(JsonStream.builder().build()).build(); MyCustomer myCustomer = new MyCustomer(42, "rob", "foo"); JsonType type = jsonb.type(MyCustomer.class); @@ -43,7 +43,7 @@ void toJson_fromJson() { @Test void list_toJson_fromJson() { - Jsonb jsonb = Jsonb.builder().adapter(new JsonStream()).build(); + Jsonb jsonb = Jsonb.builder().adapter(JsonStream.builder().build()).build(); List customers = new ArrayList<>(); customers.add(new MyCustomer(42, "rob", "foo")); diff --git a/blackbox-test/src/test/java/org/example/customer/skip/SkipTest.java b/blackbox-test/src/test/java/org/example/customer/skip/SkipTest.java index f4d148bc..aa264a6d 100644 --- a/blackbox-test/src/test/java/org/example/customer/skip/SkipTest.java +++ b/blackbox-test/src/test/java/org/example/customer/skip/SkipTest.java @@ -2,14 +2,14 @@ import io.avaje.jsonb.JsonType; import io.avaje.jsonb.Jsonb; -import io.avaje.jsonb.stream.JsonStream; +import io.avaje.json.stream.JsonStream; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; class SkipTest { - Jsonb jsonb = Jsonb.builder().adapter(new JsonStream()).build(); + Jsonb jsonb = Jsonb.builder().adapter(JsonStream.builder().build()).build(); JsonType type = jsonb.type(MyCustomer.class); @Test diff --git a/blackbox-test/src/test/java/org/example/customer/stream/StreamBasicTest.java b/blackbox-test/src/test/java/org/example/customer/stream/StreamBasicTest.java index d0363eac..11a1300d 100644 --- a/blackbox-test/src/test/java/org/example/customer/stream/StreamBasicTest.java +++ b/blackbox-test/src/test/java/org/example/customer/stream/StreamBasicTest.java @@ -1,6 +1,6 @@ package org.example.customer.stream; -import io.avaje.jsonb.JsonReader; +import io.avaje.json.*; import io.avaje.jsonb.JsonType; import io.avaje.jsonb.Jsonb; import org.junit.jupiter.api.Test; diff --git a/blackbox-test/src/test/java/org/example/customer/stream/StreamNestedTest.java b/blackbox-test/src/test/java/org/example/customer/stream/StreamNestedTest.java index fe22cb69..2e889d24 100644 --- a/blackbox-test/src/test/java/org/example/customer/stream/StreamNestedTest.java +++ b/blackbox-test/src/test/java/org/example/customer/stream/StreamNestedTest.java @@ -1,6 +1,6 @@ package org.example.customer.stream; -import io.avaje.jsonb.JsonReader; +import io.avaje.json.*; import io.avaje.jsonb.JsonType; import io.avaje.jsonb.Jsonb; import org.junit.jupiter.api.Test; diff --git a/blackbox-test/src/test/java/org/example/other/ObjectAdapterTest.java b/blackbox-test/src/test/java/org/example/other/ObjectAdapterTest.java index c86b4082..edbd674c 100644 --- a/blackbox-test/src/test/java/org/example/other/ObjectAdapterTest.java +++ b/blackbox-test/src/test/java/org/example/other/ObjectAdapterTest.java @@ -1,8 +1,7 @@ package org.example.other; -import io.avaje.jsonb.JsonAdapter; import io.avaje.jsonb.JsonType; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.*; import io.avaje.jsonb.Jsonb; import io.avaje.jsonb.Types; diff --git a/json-core/pom.xml b/json-core/pom.xml new file mode 100644 index 00000000..d8a12a9c --- /dev/null +++ b/json-core/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + io.avaje + avaje-jsonb-parent + 2.5-SNAPSHOT + + + avaje-json + + + + io.helidon.webserver + helidon-webserver + 4.1.0 + provided + true + + + + io.avaje + junit + 1.5 + test + + + + diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonAdapter.java b/json-core/src/main/java/io/avaje/json/JsonAdapter.java similarity index 70% rename from jsonb/src/main/java/io/avaje/jsonb/JsonAdapter.java rename to json-core/src/main/java/io/avaje/json/JsonAdapter.java index 38fb8217..f2748f95 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonAdapter.java +++ b/json-core/src/main/java/io/avaje/json/JsonAdapter.java @@ -13,11 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb; +package io.avaje.json; -import java.lang.reflect.Type; - -import io.avaje.jsonb.spi.ViewBuilderAware; +import io.avaje.json.view.ViewBuilderAware; /** * The core API for serialization to and from json. @@ -52,22 +50,9 @@ default boolean isViewBuilderAware() { } /** - * Return the ViewBuilder.Aware for this adapter. + * Return the ViewBuilderAware for this adapter. */ default ViewBuilderAware viewBuild() { - throw new IllegalStateException("This adapter is not ViewBuilderAware"); - } - - /** - * Factory for creating a JsonAdapter. - */ - public interface Factory { - - /** - * Create and return a JsonAdapter given the type and annotations or return null. - *

- * Returning null means that the adapter could be created by another factory. - */ - JsonAdapter create(Type type, Jsonb jsonb); + throw new UnsupportedOperationException(); } } diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonDataException.java b/json-core/src/main/java/io/avaje/json/JsonDataException.java similarity index 97% rename from jsonb/src/main/java/io/avaje/jsonb/JsonDataException.java rename to json-core/src/main/java/io/avaje/json/JsonDataException.java index db51150b..4fe1795d 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonDataException.java +++ b/json-core/src/main/java/io/avaje/json/JsonDataException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb; +package io.avaje.json; /** * Thrown when data being parsed is not encoded as valid json or attempting to write invalid json. diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonEofException.java b/json-core/src/main/java/io/avaje/json/JsonEofException.java similarity index 94% rename from jsonb/src/main/java/io/avaje/jsonb/JsonEofException.java rename to json-core/src/main/java/io/avaje/json/JsonEofException.java index 3eefe6f5..2c4b878e 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonEofException.java +++ b/json-core/src/main/java/io/avaje/json/JsonEofException.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb; +package io.avaje.json; import java.io.IOException; diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonException.java b/json-core/src/main/java/io/avaje/json/JsonException.java similarity index 98% rename from jsonb/src/main/java/io/avaje/jsonb/JsonException.java rename to json-core/src/main/java/io/avaje/json/JsonException.java index 2cf04cbf..987eaab1 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonException.java +++ b/json-core/src/main/java/io/avaje/json/JsonException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb; +package io.avaje.json; /** * Thrown when the data being parsed is not encoded as valid JSON, diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonIoException.java b/json-core/src/main/java/io/avaje/json/JsonIoException.java similarity index 97% rename from jsonb/src/main/java/io/avaje/jsonb/JsonIoException.java rename to json-core/src/main/java/io/avaje/json/JsonIoException.java index 12a4fa18..049e4122 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonIoException.java +++ b/json-core/src/main/java/io/avaje/json/JsonIoException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb; +package io.avaje.json; import java.io.IOException; diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonReader.java b/json-core/src/main/java/io/avaje/json/JsonReader.java similarity index 98% rename from jsonb/src/main/java/io/avaje/jsonb/JsonReader.java rename to json-core/src/main/java/io/avaje/json/JsonReader.java index 7abb655f..11faf409 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonReader.java +++ b/json-core/src/main/java/io/avaje/json/JsonReader.java @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb; - -import io.avaje.jsonb.spi.PropertyNames; +package io.avaje.json; import java.io.Closeable; import java.math.BigDecimal; diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonWriter.java b/json-core/src/main/java/io/avaje/json/JsonWriter.java similarity index 98% rename from jsonb/src/main/java/io/avaje/jsonb/JsonWriter.java rename to json-core/src/main/java/io/avaje/json/JsonWriter.java index abfd2dfa..a4991fd7 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonWriter.java +++ b/json-core/src/main/java/io/avaje/json/JsonWriter.java @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb; - -import io.avaje.jsonb.spi.PropertyNames; +package io.avaje.json; import java.io.Closeable; import java.io.Flushable; diff --git a/jsonb/src/main/java/io/avaje/jsonb/NullSafeAdapter.java b/json-core/src/main/java/io/avaje/json/NullSafeAdapter.java similarity index 95% rename from jsonb/src/main/java/io/avaje/jsonb/NullSafeAdapter.java rename to json-core/src/main/java/io/avaje/json/NullSafeAdapter.java index 1a439559..52ea361e 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/NullSafeAdapter.java +++ b/json-core/src/main/java/io/avaje/json/NullSafeAdapter.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb; +package io.avaje.json; -import io.avaje.jsonb.spi.ViewBuilderAware; + +import io.avaje.json.view.ViewBuilderAware; final class NullSafeAdapter implements JsonAdapter { diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/PropertyNames.java b/json-core/src/main/java/io/avaje/json/PropertyNames.java similarity index 71% rename from jsonb/src/main/java/io/avaje/jsonb/spi/PropertyNames.java rename to json-core/src/main/java/io/avaje/json/PropertyNames.java index 414f3df6..b9174a09 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/PropertyNames.java +++ b/json-core/src/main/java/io/avaje/json/PropertyNames.java @@ -1,6 +1,4 @@ -package io.avaje.jsonb.spi; - -import io.avaje.jsonb.JsonWriter; +package io.avaje.json; /** * Marker interface for IOAdapter specific property names. @@ -8,7 +6,7 @@ * This can provide support for use of names by index position where * the names have already been escaped and encoded. * - * @see JsonWriter#names(PropertyNames) + * @see JsonWriter#allNames(PropertyNames) * @see JsonWriter#name(int) */ public interface PropertyNames { diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/ArrayAdapter.java b/json-core/src/main/java/io/avaje/json/core/ArrayAdapter.java similarity index 80% rename from jsonb/src/main/java/io/avaje/jsonb/core/ArrayAdapter.java rename to json-core/src/main/java/io/avaje/json/core/ArrayAdapter.java index 10750c35..b56da944 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/ArrayAdapter.java +++ b/json-core/src/main/java/io/avaje/json/core/ArrayAdapter.java @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb.core; +package io.avaje.json.core; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import java.lang.reflect.Array; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -29,14 +28,14 @@ * This supports both primitive and object arrays. */ final class ArrayAdapter implements JsonAdapter { - static final Factory FACTORY = (type, jsonb) -> { - Type elementType = Util.arrayComponentType(type); - if (elementType == null) return null; - if (elementType == byte.class) return new ByteArray(); - Class elementClass = Util.rawType(elementType); - JsonAdapter elementAdapter = jsonb.adapter(elementType); + + static JsonAdapter create(Class elementClass, JsonAdapter elementAdapter) { return new ArrayAdapter(elementClass, elementAdapter).nullSafe(); - }; + } + + static JsonAdapter byteArray() { + return new ByteArray(); + } private final Class elementClass; private final JsonAdapter elementAdapter; @@ -75,7 +74,7 @@ public String toString() { return elementAdapter + ".array()"; } - static final class ByteArray implements JsonAdapter { + private static final class ByteArray implements JsonAdapter { @Override public byte[] fromJson(JsonReader reader) { return reader.readBinary(); diff --git a/json-core/src/main/java/io/avaje/json/core/BaseAdapters.java b/json-core/src/main/java/io/avaje/json/core/BaseAdapters.java new file mode 100644 index 00000000..91d57667 --- /dev/null +++ b/json-core/src/main/java/io/avaje/json/core/BaseAdapters.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2014 Square, Inc. + * + * Licensed 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 + * + * https://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 io.avaje.json.core; + +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonDataException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; + +import java.lang.reflect.Type; + +import static java.util.Objects.requireNonNull; + +final class BaseAdapters { + + static JsonAdapter create(Type type) { + if (type == Boolean.TYPE) return new BooleanAdapter(); + if (type == Double.TYPE) return new DoubleAdapter(); + if (type == Float.TYPE) return new FloatAdapter(); + if (type == Integer.TYPE) return new IntegerAdapter(); + if (type == Long.TYPE) return new LongAdapter(); + if (type == Boolean.class) return new BooleanAdapter().nullSafe(); + if (type == Double.class) return new DoubleAdapter().nullSafe(); + if (type == Float.class) return new FloatAdapter().nullSafe(); + if (type == Integer.class) return new IntegerAdapter().nullSafe(); + if (type == Long.class) return new LongAdapter().nullSafe(); + if (type == String.class) return new StringAdapter().nullSafe(); + + return null; + } + + private static final class BooleanAdapter implements JsonAdapter { + @Override + public Boolean fromJson(JsonReader reader) { + return reader.readBoolean(); + } + + @Override + public void toJson(JsonWriter writer, Boolean value) { + writer.value(value); + } + + @Override + public String toString() { + return "JsonAdapter(Boolean)"; + } + } + + private static final class DoubleAdapter implements JsonAdapter { + @Override + public Double fromJson(JsonReader reader) { + return reader.readDouble(); + } + + @Override + public void toJson(JsonWriter writer, Double value) { + writer.value(value); + } + + @Override + public String toString() { + return "JsonAdapter(Double)"; + } + } + + private static final class FloatAdapter implements JsonAdapter { + @Override + public Float fromJson(JsonReader reader) { + float value = (float) reader.readDouble(); + if (Float.isInfinite(value)) { // !reader.isLenient() && + throw new JsonDataException("JSON forbids NaN and infinities: " + value + " at path " + reader.location()); + } else { + return value; + } + } + + @Override + public void toJson(JsonWriter writer, Float value) { + requireNonNull(value); + writer.value(value); + } + + @Override + public String toString() { + return "JsonAdapter(Float)"; + } + } + + private static final class IntegerAdapter implements JsonAdapter { + @Override + public Integer fromJson(JsonReader reader) { + return reader.readInt(); + } + + @Override + public void toJson(JsonWriter writer, Integer value) { + writer.value(value); + } + + @Override + public String toString() { + return "JsonAdapter(Integer)"; + } + } + + private static final class LongAdapter implements JsonAdapter { + @Override + public Long fromJson(JsonReader reader) { + return reader.readLong(); + } + + @Override + public void toJson(JsonWriter writer, Long value) { + writer.value(value); + } + + @Override + public String toString() { + return "JsonAdapter(Long)"; + } + } + + private static final class StringAdapter implements JsonAdapter { + @Override + public String fromJson(JsonReader reader) { + return reader.readString(); + } + + @Override + public void toJson(JsonWriter writer, String value) { + writer.value(value); + } + + @Override + public String toString() { + return "JsonAdapter(String)"; + } + } + +} diff --git a/json-core/src/main/java/io/avaje/json/core/BasicObjectAdapter.java b/json-core/src/main/java/io/avaje/json/core/BasicObjectAdapter.java new file mode 100644 index 00000000..068a7684 --- /dev/null +++ b/json-core/src/main/java/io/avaje/json/core/BasicObjectAdapter.java @@ -0,0 +1,85 @@ +package io.avaje.json.core; + +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; + +import java.util.List; +import java.util.Map; + +final class BasicObjectAdapter implements JsonAdapter { + + private final JsonAdapter stringAdapter; + private final JsonAdapter doubleAdapter; + private final JsonAdapter intAdapter; + private final JsonAdapter longAdapter; + private final JsonAdapter booleanAdapter; + private final JsonAdapter> listAdapter; + private final JsonAdapter> mapAdapter; + + BasicObjectAdapter() { + this.stringAdapter = CoreTypes.create(String.class); + this.intAdapter = CoreTypes.create(Integer.class); + this.doubleAdapter = CoreTypes.create(Double.class); + this.longAdapter = CoreTypes.create(Long.class); + this.booleanAdapter = CoreTypes.create(Boolean.class); + this.listAdapter = CoreTypes.createList(this); + this.mapAdapter = CoreTypes.createMap(this); + } + + @Override + public Object fromJson(JsonReader reader) { + switch (reader.currentToken()) { + case BEGIN_ARRAY: + return listAdapter.fromJson(reader); + case BEGIN_OBJECT: + return mapAdapter.fromJson(reader); + case STRING: + return stringAdapter.fromJson(reader); + case NUMBER: + var d = doubleAdapter.fromJson(reader); + if (d % 1 == 0) { + return d.longValue(); + } + return d; + case BOOLEAN: + return booleanAdapter.fromJson(reader); + case NULL: + return null; + default: + throw new IllegalStateException("Expected a value but was " + reader.currentToken() + " at path " + reader.location()); + } + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public void toJson(JsonWriter writer, Object value) { + if (value == null) { + writer.nullValue(); + return; + } + final Class valueClass = value.getClass(); + if (valueClass == String.class) { + stringAdapter.toJson(writer, (String)value); + } else if (value instanceof List) { + listAdapter.toJson(writer, (List) value); + } else if (value instanceof Boolean) { + booleanAdapter.toJson(writer, (Boolean)value); + } else if (value instanceof Integer) { + intAdapter.toJson(writer, (Integer)value); + } else if (value instanceof Long) { + longAdapter.toJson(writer, (Long)value); + } else if (value instanceof Double) { + doubleAdapter.toJson(writer, (Double)value); + } else if (Map.class.isAssignableFrom(valueClass)) { + mapAdapter.toJson(writer, (Map)value); + } else { + throw new UnsupportedOperationException("Type not supported " + value.getClass()); + } + } + + @Override + public String toString() { + return "BasicObjectAdapter"; + } +} diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/CollectionAdapter.java b/json-core/src/main/java/io/avaje/json/core/CollectionAdapter.java similarity index 65% rename from jsonb/src/main/java/io/avaje/jsonb/core/CollectionAdapter.java rename to json-core/src/main/java/io/avaje/json/core/CollectionAdapter.java index 3c557254..526ce505 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/CollectionAdapter.java +++ b/json-core/src/main/java/io/avaje/json/core/CollectionAdapter.java @@ -13,46 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb.core; +package io.avaje.json.core; -import io.avaje.jsonb.*; -import io.avaje.jsonb.spi.ViewBuilder; -import io.avaje.jsonb.spi.ViewBuilderAware; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.view.ViewBuilder; +import io.avaje.json.view.ViewBuilderAware; import java.lang.invoke.MethodHandle; -import java.lang.reflect.Type; import java.util.*; /** * Converts collection types to JSON arrays containing their converted contents. */ -abstract class CollectionAdapter, T> implements JsonAdapter, ViewBuilderAware { +abstract class CollectionAdapter, T> implements ViewBuilderAware, JsonAdapter { - static final JsonAdapter.Factory FACTORY = (type, jsonb) -> { - Class rawType = Util.rawType(type); - if (rawType == List.class || rawType == Collection.class) { - return newListAdapter(type, jsonb).nullSafe(); - } else if (rawType == Set.class) { - return newSetAdapter(type, jsonb).nullSafe(); - } - return null; - }; - - static JsonAdapter> newListAdapter(Type type, Jsonb jsonb) { - Type elementType = Util.collectionElementType(type); - JsonAdapter elementAdapter = jsonb.adapter(elementType); - return new CollectionAdapter, T>(elementAdapter) { + static JsonAdapter> createList(JsonAdapter elementAdapter) { + return new CollectionAdapter<>(elementAdapter) { @Override - Collection newCollection() { + List newCollection() { return new ArrayList<>(); } }; } - static JsonAdapter> newSetAdapter(Type type, Jsonb jsonb) { - Type elementType = Util.collectionElementType(type); - JsonAdapter elementAdapter = jsonb.adapter(elementType); - return new CollectionAdapter, T>(elementAdapter) { + static JsonAdapter> createSet(JsonAdapter elementAdapter) { + return new CollectionAdapter<>(elementAdapter) { @Override Set newCollection() { return new LinkedHashSet<>(); diff --git a/json-core/src/main/java/io/avaje/json/core/CoreTypes.java b/json-core/src/main/java/io/avaje/json/core/CoreTypes.java new file mode 100644 index 00000000..f7e6007b --- /dev/null +++ b/json-core/src/main/java/io/avaje/json/core/CoreTypes.java @@ -0,0 +1,125 @@ +package io.avaje.json.core; + +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; + +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import static java.util.Objects.requireNonNull; + +/** + * Provides core JsonAdapter for common types. + *

+ * Supports Boolean, Integer, Long, Double, Float, String. + */ +public final class CoreTypes { + + private static final Map> adapterCache = new ConcurrentHashMap<>(); + private static final NullPlaceholder NULL_PLACEHOLDER = new NullPlaceholder(); + + /** + * Return a core supported type adapter or null. + *

+ * Supports Boolean, Integer, Long, Double, Float, String. + * + * @param type The type to get the adapter for. + * @return The JsonAdapter for the type or null. + */ + @SuppressWarnings({"unchecked"}) + public static JsonAdapter create(Type type) { + final var adapter = adapterCache.computeIfAbsent(type, CoreTypes::createAdapter); + return adapter == NULL_PLACEHOLDER ? null : (JsonAdapter) adapter; + } + + /** + * Create a JsonAdapter for an Array of the given element type. + */ + @SuppressWarnings("unchecked") + public static JsonAdapter createArray(Class elementType) { + final var adapter = (JsonAdapter) createAdapter(elementType); + return createArray(elementType, adapter); + } + + /** + * Create a JsonAdapter for an Array of the given type. + * + * @param elementType The element type of the array. + * @return The JsonAdapter for an Array of the given type. + */ + @SuppressWarnings("unchecked") + public static JsonAdapter createArray(Class elementType, JsonAdapter adapter) { + return (JsonAdapter) ArrayAdapter.create(requireNonNull(elementType), requireNonNull(adapter)); + } + + /** + * Return a JsonAdapter for {@code byte[]}. + */ + public static JsonAdapter byteArray() { + return ArrayAdapter.byteArray(); + } + + /** + * Create a JsonAdapter for a Map with a given adapter for the values. + * + * @param valueAdapter The JsonAdapter used for the values in the map. + * @return The JsonAdapter for the map. + */ + public static JsonAdapter> createMap(JsonAdapter valueAdapter) { + return MapAdapter.create(valueAdapter); + } + + /** + * Create a JsonAdapter for a List with a given adapter for the elements. + * + * @param elementAdapter The JsonAdapter used for the elements in the list. + * @return The JsonAdapter for the list. + */ + public static JsonAdapter> createList(JsonAdapter elementAdapter) { + return CollectionAdapter.createList(elementAdapter); + } + + /** + * Create a JsonAdapter for a Set with a given adapter for the elements. + * + * @param elementAdapter The JsonAdapter used for the elements in the set. + * @return The JsonAdapter for the set. + */ + public static JsonAdapter> createSet(JsonAdapter elementAdapter) { + return CollectionAdapter.createSet(elementAdapter); + } + + /** + * Create a JsonAdapter that supports simple types including scalar + * types of: String, Integer, Long, Double, Boolean plus List and Map + * of those types. + */ + public static JsonAdapter createBasicObject() { + return new BasicObjectAdapter(); + } + + private static JsonAdapter createAdapter(Type type) { + final var adapter = BaseAdapters.create(type); + if (adapter != null) { + return adapter; + } + return NULL_PLACEHOLDER; + } + + static final class NullPlaceholder implements JsonAdapter { + + @Override + public void toJson(JsonWriter writer, Void value) { + throw new UnsupportedOperationException(); + } + + @Override + public Void fromJson(JsonReader reader) { + throw new UnsupportedOperationException(); + } + } +} diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/MapAdapter.java b/json-core/src/main/java/io/avaje/json/core/MapAdapter.java similarity index 77% rename from jsonb/src/main/java/io/avaje/jsonb/core/MapAdapter.java rename to json-core/src/main/java/io/avaje/json/core/MapAdapter.java index 23bd21bb..115d8fb2 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/MapAdapter.java +++ b/json-core/src/main/java/io/avaje/json/core/MapAdapter.java @@ -13,9 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb.core; +package io.avaje.json.core; -import io.avaje.jsonb.*; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonDataException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import java.lang.reflect.Type; import java.util.LinkedHashMap; @@ -26,24 +29,14 @@ */ final class MapAdapter implements JsonAdapter> { - static final Factory FACTORY = - (type, jsonb) -> { - final var rawType = Util.rawType(type); - if (rawType != Map.class) { - return null; - } - final var valueTypes = Util.mapValueTypes(type, rawType); - - if (valueTypes[0] != String.class) { - return null; - } - return new MapAdapter<>(jsonb, valueTypes[1]).nullSafe(); - }; + static JsonAdapter> create(JsonAdapter valueAdapter) { + return new MapAdapter<>(valueAdapter); + } private final JsonAdapter valueAdapter; - MapAdapter(Jsonb jsonb, Type valueType) { - this.valueAdapter = jsonb.adapter(valueType); + MapAdapter(JsonAdapter valueAdapter) { + this.valueAdapter = valueAdapter; } @Override diff --git a/json-core/src/main/java/io/avaje/json/core/package-info.java b/json-core/src/main/java/io/avaje/json/core/package-info.java new file mode 100644 index 00000000..50679121 --- /dev/null +++ b/json-core/src/main/java/io/avaje/json/core/package-info.java @@ -0,0 +1,6 @@ +/** + * Core JsonAdapters provided for basic types. + * + * @see io.avaje.json.core.CoreTypes + */ +package io.avaje.json.core; diff --git a/json-core/src/main/java/io/avaje/json/stream/BufferRecycleStrategy.java b/json-core/src/main/java/io/avaje/json/stream/BufferRecycleStrategy.java new file mode 100644 index 00000000..fa942a21 --- /dev/null +++ b/json-core/src/main/java/io/avaje/json/stream/BufferRecycleStrategy.java @@ -0,0 +1,15 @@ +package io.avaje.json.stream; + +/** Strategy for recycling buffers used in parsing and generation. */ +public enum BufferRecycleStrategy { + + /** Do not perform any sort of recycling. */ + NO_RECYCLING, + /** A lock free implementation designed for virtual thread use */ + LOCK_FREE, + /** Use Thread Locals for recycling buffers */ + THREAD_LOCAL, + /** Use 2 recyclers and switch between them depending on the nature of thread (virtual or not) */ + HYBRID_POOL; + +} diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/BufferedJsonWriter.java b/json-core/src/main/java/io/avaje/json/stream/BufferedJsonWriter.java similarity index 77% rename from jsonb/src/main/java/io/avaje/jsonb/spi/BufferedJsonWriter.java rename to json-core/src/main/java/io/avaje/json/stream/BufferedJsonWriter.java index ee50fbbf..fa7a0325 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/BufferedJsonWriter.java +++ b/json-core/src/main/java/io/avaje/json/stream/BufferedJsonWriter.java @@ -1,6 +1,6 @@ -package io.avaje.jsonb.spi; +package io.avaje.json.stream; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonWriter; /** * Provides a JsonWriter optimised for returning json as string content. diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/BytesJsonWriter.java b/json-core/src/main/java/io/avaje/json/stream/BytesJsonWriter.java similarity index 75% rename from jsonb/src/main/java/io/avaje/jsonb/spi/BytesJsonWriter.java rename to json-core/src/main/java/io/avaje/json/stream/BytesJsonWriter.java index 323c07e4..8be8bee6 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/BytesJsonWriter.java +++ b/json-core/src/main/java/io/avaje/json/stream/BytesJsonWriter.java @@ -1,6 +1,6 @@ -package io.avaje.jsonb.spi; +package io.avaje.json.stream; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonWriter; /** * JsonWriter optimised for returning json as byte array. diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/DJsonOutput.java b/json-core/src/main/java/io/avaje/json/stream/DJsonOutput.java similarity index 95% rename from jsonb/src/main/java/io/avaje/jsonb/stream/DJsonOutput.java rename to json-core/src/main/java/io/avaje/json/stream/DJsonOutput.java index 44ebcd92..14fd34ab 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/DJsonOutput.java +++ b/json-core/src/main/java/io/avaje/json/stream/DJsonOutput.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream; import java.io.IOException; import java.io.OutputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/DelegateJsonWriter.java b/json-core/src/main/java/io/avaje/json/stream/DelegateJsonWriter.java similarity index 97% rename from jsonb/src/main/java/io/avaje/jsonb/spi/DelegateJsonWriter.java rename to json-core/src/main/java/io/avaje/json/stream/DelegateJsonWriter.java index be26442d..82ab66e3 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/DelegateJsonWriter.java +++ b/json-core/src/main/java/io/avaje/json/stream/DelegateJsonWriter.java @@ -1,6 +1,7 @@ -package io.avaje.jsonb.spi; +package io.avaje.json.stream; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; import java.math.BigDecimal; import java.math.BigInteger; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonOutput.java b/json-core/src/main/java/io/avaje/json/stream/JsonOutput.java similarity index 97% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JsonOutput.java rename to json-core/src/main/java/io/avaje/json/stream/JsonOutput.java index 19a5da7c..95dafcbc 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonOutput.java +++ b/json-core/src/main/java/io/avaje/json/stream/JsonOutput.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream; import io.helidon.webserver.http.ServerResponse; diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/JsonStreamAdapter.java b/json-core/src/main/java/io/avaje/json/stream/JsonStream.java similarity index 56% rename from jsonb/src/main/java/io/avaje/jsonb/spi/JsonStreamAdapter.java rename to json-core/src/main/java/io/avaje/json/stream/JsonStream.java index 950912e7..11754a8b 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/JsonStreamAdapter.java +++ b/json-core/src/main/java/io/avaje/json/stream/JsonStream.java @@ -1,15 +1,16 @@ -package io.avaje.jsonb.spi; +package io.avaje.json.stream; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.stream.JsonOutput; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; +import io.avaje.json.stream.core.JsonStreamBuilder; import java.io.*; /** * Provides the underlying JsonReader and JsonWriter to use. */ -public interface JsonStreamAdapter { +public interface JsonStream { /** * Return the JsonReader given json string content. @@ -63,8 +64,34 @@ public interface JsonStreamAdapter { * escaping quotes and encoding to bytes so that the names can * be written more efficiently. * - * @see JsonWriter#names(PropertyNames) + * @see JsonWriter#allNames(PropertyNames) * @see JsonWriter#name(int) */ PropertyNames properties(String... names); + + /** + * Create and return a builder for the default JsonStreamAdapter implementation. + */ + static Builder builder() { + return new JsonStreamBuilder(); + } + + /** Used to build JsonStream with custom settings. */ + interface Builder { + + /** Set to true to serialize nulls. Defaults to false. */ + Builder serializeNulls(boolean serializeNulls); + + /** Set to true to serialize empty collections. Defaults to false. */ + Builder serializeEmpty(boolean serializeEmpty); + + /** Set to true to fail on unknown properties. Defaults to false. */ + Builder failOnUnknown(boolean failOnUnknown); + + /** Determines how byte buffers are recycled */ + Builder bufferRecycling(BufferRecycleStrategy strategy); + + /** Build and return the JsonStream. */ + JsonStream build(); + } } diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/NimaJsonOutput.java b/json-core/src/main/java/io/avaje/json/stream/NimaJsonOutput.java similarity index 97% rename from jsonb/src/main/java/io/avaje/jsonb/stream/NimaJsonOutput.java rename to json-core/src/main/java/io/avaje/json/stream/NimaJsonOutput.java index 6c5ec8e2..63282951 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/NimaJsonOutput.java +++ b/json-core/src/main/java/io/avaje/json/stream/NimaJsonOutput.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream; import java.io.IOException; import java.io.OutputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/Base64.java b/json-core/src/main/java/io/avaje/json/stream/core/Base64.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/Base64.java rename to json-core/src/main/java/io/avaje/json/stream/core/Base64.java index b8d68b18..768dc7dc 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/Base64.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/Base64.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import java.util.Arrays; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/BufferRecycler.java b/json-core/src/main/java/io/avaje/json/stream/core/BufferRecycler.java similarity index 84% rename from jsonb/src/main/java/io/avaje/jsonb/stream/BufferRecycler.java rename to json-core/src/main/java/io/avaje/json/stream/core/BufferRecycler.java index b2f5f7d5..2731e718 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/BufferRecycler.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/BufferRecycler.java @@ -1,8 +1,9 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.stream.HybridBufferRecycler.StripedLockFreePool; -import io.avaje.jsonb.stream.Recyclers.NonRecyclingPool; -import io.avaje.jsonb.stream.Recyclers.ThreadLocalPool; +import io.avaje.json.stream.JsonOutput; +import io.avaje.json.stream.core.HybridBufferRecycler.StripedLockFreePool; +import io.avaje.json.stream.core.Recyclers.NonRecyclingPool; +import io.avaje.json.stream.core.Recyclers.ThreadLocalPool; import java.io.InputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonStream.java b/json-core/src/main/java/io/avaje/json/stream/core/CoreJsonStream.java similarity index 63% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JsonStream.java rename to json-core/src/main/java/io/avaje/json/stream/core/CoreJsonStream.java index 9545ff29..bd524c4c 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonStream.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/CoreJsonStream.java @@ -1,70 +1,23 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.spi.*; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; +import io.avaje.json.stream.*; import java.io.*; import java.nio.charset.StandardCharsets; /** Default implementation of JsonStreamAdapter provided with Jsonb. */ -public final class JsonStream implements JsonStreamAdapter { - - /** Used to build JsonStream with custom settings. */ - public static final class Builder { - - private BufferRecycleStrategy strategy = BufferRecycleStrategy.HYBRID_POOL; - private boolean serializeNulls; - private boolean serializeEmpty; - private boolean failOnUnknown; - - /** Set to true to serialize nulls. Defaults to false. */ - public Builder serializeNulls(boolean serializeNulls) { - this.serializeNulls = serializeNulls; - return this; - } - - /** Set to true to serialize empty collections. Defaults to false. */ - public Builder serializeEmpty(boolean serializeEmpty) { - this.serializeEmpty = serializeEmpty; - return this; - } - - /** Set to true to fail on unknown properties. Defaults to false. */ - public Builder failOnUnknown(boolean failOnUnknown) { - this.failOnUnknown = failOnUnknown; - return this; - } - - /** Determines how byte buffers are recycled */ - Builder bufferRecycling(BufferRecycleStrategy strategy) { - this.strategy = strategy; - return this; - } - - /** Build and return the JsonStream. */ - public JsonStream build() { - return new JsonStream(serializeNulls, serializeEmpty, failOnUnknown, strategy); - } - } +final class CoreJsonStream implements JsonStream { private final boolean serializeNulls; private final boolean serializeEmpty; private final boolean failOnUnknown; private final BufferRecycler recycle; - /** Create with the given default configuration. */ - public JsonStream() { - this(false, false, false); - } - - /** Create additionally providing the jsonFactory. */ - public JsonStream(boolean serializeNulls, boolean serializeEmpty, boolean failOnUnknown) { - this(serializeNulls, serializeEmpty, failOnUnknown, BufferRecycleStrategy.HYBRID_POOL); - } - /** Create additionally providing the jsonFactory. */ - public JsonStream( + CoreJsonStream( boolean serializeNulls, boolean serializeEmpty, boolean failOnUnknown, @@ -72,7 +25,18 @@ public JsonStream( this.serializeNulls = serializeNulls; this.serializeEmpty = serializeEmpty; this.failOnUnknown = failOnUnknown; - this.recycle = recycle.recycler(); + this.recycle = init2Recycler(recycle); + } + + private static BufferRecycler init2Recycler(BufferRecycleStrategy recycle) { + switch (recycle) { + case NO_RECYCLING: return BufferRecycler.nonRecyclingPool(); + case LOCK_FREE: return BufferRecycler.lockFreePool(); + case THREAD_LOCAL: return BufferRecycler.threadLocalPool(); + case HYBRID_POOL: return BufferRecycler.hybrid(); + default: + throw new IllegalStateException(); + } } /** @@ -85,8 +49,8 @@ public JsonStream( * * } */ - public static Builder builder() { - return new Builder(); + public static JsonStreamBuilder builder() { + return new JsonStreamBuilder(); } @Override diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/Escape.java b/json-core/src/main/java/io/avaje/json/stream/core/Escape.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/Escape.java rename to json-core/src/main/java/io/avaje/json/stream/core/Escape.java index 2f01b320..558ad8dd 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/Escape.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/Escape.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/Grisu3.java b/json-core/src/main/java/io/avaje/json/stream/core/Grisu3.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/Grisu3.java rename to json-core/src/main/java/io/avaje/json/stream/core/Grisu3.java index b8cf7f73..849bbbbb 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/Grisu3.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/Grisu3.java @@ -31,7 +31,7 @@ // Modified by Rikard Pavelic do avoid allocations // and unused code paths due to external checks -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; final class Grisu3 { diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/HybridBufferRecycler.java b/json-core/src/main/java/io/avaje/json/stream/core/HybridBufferRecycler.java similarity index 98% rename from jsonb/src/main/java/io/avaje/jsonb/stream/HybridBufferRecycler.java rename to json-core/src/main/java/io/avaje/json/stream/core/HybridBufferRecycler.java index 8fddc5dc..394b060b 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/HybridBufferRecycler.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/HybridBufferRecycler.java @@ -1,6 +1,7 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.stream.Recyclers.ThreadLocalPool; +import io.avaje.json.stream.JsonOutput; +import io.avaje.json.stream.core.Recyclers.ThreadLocalPool; import java.io.InputStream; import java.lang.invoke.MethodHandle; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JGenerator.java b/json-core/src/main/java/io/avaje/json/stream/core/JGenerator.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JGenerator.java rename to json-core/src/main/java/io/avaje/json/stream/core/JGenerator.java index 0fcc40c0..dcdf9d48 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JGenerator.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/JGenerator.java @@ -1,6 +1,7 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.JsonIoException; +import io.avaje.json.JsonIoException; +import io.avaje.json.stream.JsonOutput; import java.io.IOException; import java.math.BigDecimal; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JParser.java b/json-core/src/main/java/io/avaje/json/stream/core/JParser.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JParser.java rename to json-core/src/main/java/io/avaje/json/stream/core/JParser.java index b38d76b4..8d8db599 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JParser.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/JParser.java @@ -1,8 +1,8 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.JsonDataException; -import io.avaje.jsonb.JsonEofException; -import io.avaje.jsonb.JsonIoException; +import io.avaje.json.JsonDataException; +import io.avaje.json.JsonEofException; +import io.avaje.json.JsonIoException; import java.io.ByteArrayOutputStream; import java.io.EOFException; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonGenerator.java b/json-core/src/main/java/io/avaje/json/stream/core/JsonGenerator.java similarity index 97% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JsonGenerator.java rename to json-core/src/main/java/io/avaje/json/stream/core/JsonGenerator.java index eaba3849..5dd3df8d 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonGenerator.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/JsonGenerator.java @@ -1,4 +1,6 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; + +import io.avaje.json.stream.JsonOutput; import java.io.Closeable; import java.io.Flushable; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonNames.java b/json-core/src/main/java/io/avaje/json/stream/core/JsonNames.java similarity index 94% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JsonNames.java rename to json-core/src/main/java/io/avaje/json/stream/core/JsonNames.java index 64e85e4a..433b4342 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonNames.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/JsonNames.java @@ -1,6 +1,6 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.json.PropertyNames; import java.util.*; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonParser.java b/json-core/src/main/java/io/avaje/json/stream/core/JsonParser.java similarity index 98% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JsonParser.java rename to json-core/src/main/java/io/avaje/json/stream/core/JsonParser.java index a46eadc0..41db3d5c 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonParser.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/JsonParser.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import java.io.Closeable; import java.io.InputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonReadAdapter.java b/json-core/src/main/java/io/avaje/json/stream/core/JsonReadAdapter.java similarity index 96% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JsonReadAdapter.java rename to json-core/src/main/java/io/avaje/json/stream/core/JsonReadAdapter.java index a15a6b84..32ba92b8 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonReadAdapter.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/JsonReadAdapter.java @@ -1,7 +1,7 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.json.JsonReader; +import io.avaje.json.PropertyNames; import java.math.BigDecimal; import java.math.BigInteger; diff --git a/json-core/src/main/java/io/avaje/json/stream/core/JsonStreamBuilder.java b/json-core/src/main/java/io/avaje/json/stream/core/JsonStreamBuilder.java new file mode 100644 index 00000000..a0503bda --- /dev/null +++ b/json-core/src/main/java/io/avaje/json/stream/core/JsonStreamBuilder.java @@ -0,0 +1,59 @@ +package io.avaje.json.stream.core; + +import io.avaje.json.stream.BufferRecycleStrategy; +import io.avaje.json.stream.JsonStream; + +/** + * Used to build the default JsonStream implementation with custom settings. + */ +public final class JsonStreamBuilder implements JsonStream.Builder { + + private BufferRecycleStrategy strategy = BufferRecycleStrategy.HYBRID_POOL; + private boolean serializeNulls; + private boolean serializeEmpty; + private boolean failOnUnknown; + + /** + * Set to true to serialize nulls. Defaults to false. + */ + @Override + public JsonStreamBuilder serializeNulls(boolean serializeNulls) { + this.serializeNulls = serializeNulls; + return this; + } + + /** + * Set to true to serialize empty collections. Defaults to false. + */ + @Override + public JsonStreamBuilder serializeEmpty(boolean serializeEmpty) { + this.serializeEmpty = serializeEmpty; + return this; + } + + /** + * Set to true to fail on unknown properties. Defaults to false. + */ + @Override + public JsonStreamBuilder failOnUnknown(boolean failOnUnknown) { + this.failOnUnknown = failOnUnknown; + return this; + } + + /** + * Determines how byte buffers are recycled + */ + @Override + public JsonStreamBuilder bufferRecycling(BufferRecycleStrategy strategy) { + this.strategy = strategy; + return this; + } + + /** + * Build and return the JsonStream. + */ + @Override + public JsonStream build() { + return new CoreJsonStream(serializeNulls, serializeEmpty, failOnUnknown, strategy); + } +} diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonWriteAdapter.java b/json-core/src/main/java/io/avaje/json/stream/core/JsonWriteAdapter.java similarity index 98% rename from jsonb/src/main/java/io/avaje/jsonb/stream/JsonWriteAdapter.java rename to json-core/src/main/java/io/avaje/json/stream/core/JsonWriteAdapter.java index d9986e28..833a55f1 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/JsonWriteAdapter.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/JsonWriteAdapter.java @@ -1,7 +1,7 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; import java.math.BigDecimal; import java.math.BigInteger; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/NumberParser.java b/json-core/src/main/java/io/avaje/json/stream/core/NumberParser.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/NumberParser.java rename to json-core/src/main/java/io/avaje/json/stream/core/NumberParser.java index a39666d8..a2e1cd0b 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/NumberParser.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/NumberParser.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import java.math.BigDecimal; import java.math.BigInteger; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/NumberWriter.java b/json-core/src/main/java/io/avaje/json/stream/core/NumberWriter.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/NumberWriter.java rename to json-core/src/main/java/io/avaje/json/stream/core/NumberWriter.java index a0e05d77..ee16eb14 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/NumberWriter.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/NumberWriter.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; final class NumberWriter { diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/ReaderInputStream.java b/json-core/src/main/java/io/avaje/json/stream/core/ReaderInputStream.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/ReaderInputStream.java rename to json-core/src/main/java/io/avaje/json/stream/core/ReaderInputStream.java index 97483ff5..f1491762 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/ReaderInputStream.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/ReaderInputStream.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import java.io.IOException; import java.io.InputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/Recyclers.java b/json-core/src/main/java/io/avaje/json/stream/core/Recyclers.java similarity index 97% rename from jsonb/src/main/java/io/avaje/jsonb/stream/Recyclers.java rename to json-core/src/main/java/io/avaje/json/stream/core/Recyclers.java index 04347dbb..d2484ac0 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/Recyclers.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/Recyclers.java @@ -1,4 +1,6 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; + +import io.avaje.json.stream.JsonOutput; import java.io.InputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/WriterOutputStream.java b/json-core/src/main/java/io/avaje/json/stream/core/WriterOutputStream.java similarity index 99% rename from jsonb/src/main/java/io/avaje/jsonb/stream/WriterOutputStream.java rename to json-core/src/main/java/io/avaje/json/stream/core/WriterOutputStream.java index 7dfb1e97..efe46ac6 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/WriterOutputStream.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/WriterOutputStream.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import java.io.IOException; import java.io.OutputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/package-info.java b/json-core/src/main/java/io/avaje/json/stream/core/package-info.java similarity index 82% rename from jsonb/src/main/java/io/avaje/jsonb/stream/package-info.java rename to json-core/src/main/java/io/avaje/json/stream/core/package-info.java index 36cccbb3..985b1a21 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/package-info.java +++ b/json-core/src/main/java/io/avaje/json/stream/core/package-info.java @@ -8,6 +8,6 @@ * with one based on jackson-core to do the underlying JSON parsing * and generation. * - * @see io.avaje.jsonb.stream.JsonStream + * @see io.avaje.json.stream.core.JsonStreamBuilder */ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; diff --git a/json-core/src/main/java/io/avaje/json/stream/package-info.java b/json-core/src/main/java/io/avaje/json/stream/package-info.java new file mode 100644 index 00000000..f8638b68 --- /dev/null +++ b/json-core/src/main/java/io/avaje/json/stream/package-info.java @@ -0,0 +1,7 @@ +/** + * Reading and writing JSON content. + * + * @see io.avaje.json.stream.JsonStream + * @see io.avaje.json.stream.JsonStream#builder() + */ +package io.avaje.json.stream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/ViewBuilder.java b/json-core/src/main/java/io/avaje/json/view/ViewBuilder.java similarity index 94% rename from jsonb/src/main/java/io/avaje/jsonb/spi/ViewBuilder.java rename to json-core/src/main/java/io/avaje/json/view/ViewBuilder.java index 613e9e88..80adf6e7 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/ViewBuilder.java +++ b/json-core/src/main/java/io/avaje/json/view/ViewBuilder.java @@ -1,6 +1,6 @@ -package io.avaje.jsonb.spi; +package io.avaje.json.view; -import io.avaje.jsonb.JsonAdapter; +import io.avaje.json.JsonAdapter; import java.lang.invoke.MethodHandle; diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/ViewBuilderAware.java b/json-core/src/main/java/io/avaje/json/view/ViewBuilderAware.java similarity index 95% rename from jsonb/src/main/java/io/avaje/jsonb/spi/ViewBuilderAware.java rename to json-core/src/main/java/io/avaje/json/view/ViewBuilderAware.java index 0f49975b..0d675ee2 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/ViewBuilderAware.java +++ b/json-core/src/main/java/io/avaje/json/view/ViewBuilderAware.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.spi; +package io.avaje.json.view; import java.lang.invoke.MethodHandle; diff --git a/json-core/src/main/java/io/avaje/json/view/package-info.java b/json-core/src/main/java/io/avaje/json/view/package-info.java new file mode 100644 index 00000000..4b254bd5 --- /dev/null +++ b/json-core/src/main/java/io/avaje/json/view/package-info.java @@ -0,0 +1,9 @@ +/** + * Defines the ability to build "Views" that will render only selected + * properties of a JsonAdapter. + *

+ * For example, you might have an adapter for a Customer class that has 10 + * properties and want to define a view that only has the name and email + * properties. + */ +package io.avaje.json.view; diff --git a/json-core/src/main/java/module-info.java b/json-core/src/main/java/module-info.java new file mode 100644 index 00000000..f0bdb502 --- /dev/null +++ b/json-core/src/main/java/module-info.java @@ -0,0 +1,10 @@ +module io.avaje.json { + + exports io.avaje.json; + exports io.avaje.json.core; + exports io.avaje.json.stream; + exports io.avaje.json.stream.core; + exports io.avaje.json.view; + + requires static io.helidon.webserver; +} diff --git a/json-core/src/test/java/io/avaje/json/core/CoreTypesTest.java b/json-core/src/test/java/io/avaje/json/core/CoreTypesTest.java new file mode 100644 index 00000000..2791d21f --- /dev/null +++ b/json-core/src/test/java/io/avaje/json/core/CoreTypesTest.java @@ -0,0 +1,84 @@ +package io.avaje.json.core; + +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.stream.BufferedJsonWriter; +import io.avaje.json.stream.JsonStream; +import org.junit.jupiter.api.Test; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.*; + +class CoreTypesTest { + + static final JsonStream stream = JsonStream.builder().build(); + + @Test + void mapOfScalar() { + JsonAdapter longAdapter = CoreTypes.create(Long.class); + JsonAdapter> mapAdapter = CoreTypes.createMap(longAdapter); + + Map map = new LinkedHashMap<>(); + map.put("one", 45L); + map.put("two", 93L); + + BufferedJsonWriter writer = stream.bufferedWriter(); + mapAdapter.toJson(writer, map); + String asJson = writer.result(); + assertThat(asJson).isEqualTo("{\"one\":45,\"two\":93}"); + + JsonReader reader = stream.reader(asJson); + Map fromJsonMap = mapAdapter.fromJson(reader); + + assertThat(fromJsonMap).containsOnlyKeys("one", "two"); + } + + @Test + void listOfScalar() { + JsonAdapter longAdapter = CoreTypes.create(Long.class); + JsonAdapter> listAdapter = CoreTypes.createList(longAdapter); + + List vals = List.of(54L, 21L, 63L); + + BufferedJsonWriter writer = stream.bufferedWriter(); + listAdapter.toJson(writer, vals); + String asJson = writer.result(); + assertThat(asJson).isEqualTo("[54,21,63]"); + + JsonReader reader = stream.reader(asJson); + List fromJsnoList = listAdapter.fromJson(reader); + + assertThat(fromJsnoList).containsExactly(54L, 21L, 63L); + } + + @SuppressWarnings("unchecked") + @Test + void createBasicObject() { + JsonAdapter basicObject = CoreTypes.createBasicObject(); + + Map inner = new LinkedHashMap<>(); + inner.put("nm", "r"); + inner.put("va", 56L); + + Map map = new LinkedHashMap<>(); + map.put("one", 45L); + map.put("two", List.of(45, 46)); + map.put("three", inner); + + + BufferedJsonWriter writer = stream.bufferedWriter(); + basicObject.toJson(writer, map); + String asJson = writer.result(); + assertThat(asJson).isEqualTo("{\"one\":45,\"two\":[45,46],\"three\":{\"nm\":\"r\",\"va\":56}}"); + + JsonReader reader = stream.reader(asJson); + Map resultMap = (Map)basicObject.fromJson(reader); + assertThat(resultMap.get("one")).isEqualTo(45L); + assertThat(resultMap.get("two")).isEqualTo(List.of(45L, 46L)); + assertThat(resultMap.get("three")).isInstanceOf(Map.class); + assertThat(resultMap.get("three")).isEqualTo(inner); + } +} diff --git a/json-core/src/test/java/io/avaje/json/stream/JsonStreamTest.java b/json-core/src/test/java/io/avaje/json/stream/JsonStreamTest.java new file mode 100644 index 00000000..51fd3c11 --- /dev/null +++ b/json-core/src/test/java/io/avaje/json/stream/JsonStreamTest.java @@ -0,0 +1,62 @@ +package io.avaje.json.stream; + +import io.avaje.json.JsonReader; +import io.avaje.json.PropertyNames; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class JsonStreamTest { + + static final String input = "{\"key0\":\"val0\", \"key1\": 42, \"key2\": true, \"key3\":\"val3\"}"; + + static final JsonStream stream = JsonStream.builder().build(); + // PropertyNames names = stream.properties("key0", "key1", "key2", "key3"); + static final PropertyNames names = stream.properties("key0", "key2"); + + @Test + void readKnownProperties() { + + String key0 = null; + Long key1 = null; + Boolean key2 = null; + String key3 = null; + + try (JsonReader reader = stream.reader(input)) { + // can use known property names for performance + reader.beginObject(names); + while (reader.hasNextField()) { + final String fieldName = reader.nextField(); + switch (fieldName) { + case "key0": + key0 = reader.readString(); + break; + case "key1": + key1 = reader.readLong(); + break; + case "key2": + key2 = reader.readBoolean(); + break; + case "key3": + key3 = reader.readString(); + break; + default: + reader.unmappedField(fieldName); + reader.skipValue(); + } + } + reader.endObject(); + } + + assertThat(key0).isEqualTo("val0"); + assertThat(key1).isEqualTo(42L); + assertThat(key2).isEqualTo(true); + assertThat(key3).isEqualTo("val3"); + } + + @Test + void readUnknown() { + + } + +} diff --git a/jsonb/src/test/java/io/avaje/jsonb/stream/ArrayTest.java b/json-core/src/test/java/io/avaje/json/stream/core/ArrayTest.java similarity index 75% rename from jsonb/src/test/java/io/avaje/jsonb/stream/ArrayTest.java rename to json-core/src/test/java/io/avaje/json/stream/core/ArrayTest.java index 6dc5a578..70417ad7 100644 --- a/jsonb/src/test/java/io/avaje/jsonb/stream/ArrayTest.java +++ b/json-core/src/test/java/io/avaje/json/stream/core/ArrayTest.java @@ -1,15 +1,50 @@ -package io.avaje.jsonb.stream; - -import io.avaje.jsonb.JsonDataException; -import io.avaje.jsonb.JsonReader; +package io.avaje.json.stream.core; + +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonDataException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.core.CoreTypes; +import io.avaje.json.stream.JsonStream; import org.junit.jupiter.api.Test; +import java.io.StringWriter; + import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; class ArrayTest { - final JsonStream adapter = JsonStream.builder().serializeNulls(true).serializeEmpty(true).failOnUnknown(false).build(); + final JsonStream adapter = CoreJsonStream.builder().serializeNulls(true).serializeEmpty(true).failOnUnknown(false).build(); + + @Test + void coreTypes_createArray() { + JsonAdapter arrayOfLong = CoreTypes.createArray(Long.class); + try (JsonReader reader = adapter.reader("[1,2,3]")) { + Long[] asLong = arrayOfLong.fromJson(reader); + assertThat(asLong).hasSize(3); + assertThat(asLong).contains(1L, 2L, 3L); + } + + Long[] longArrayVal = {42L, 43L}; + StringWriter writer = new StringWriter(); + try (JsonWriter jsonWriter = adapter.writer(writer)) { + arrayOfLong.toJson(jsonWriter, longArrayVal); + } + assertThat(writer.toString()).isEqualTo("[42,43]"); + } + + @Test + void coreTypes_createArray2() { + JsonAdapter longAdapter = CoreTypes.create(Long.class); + JsonAdapter arrayOfLong = CoreTypes.createArray(Long.class, longAdapter); + try (JsonReader reader = adapter.reader("[1,2,3]")) { + Object result = arrayOfLong.fromJson(reader); + Long[] asLong = (Long[]) result; + assertThat(asLong).hasSize(3); + assertThat(asLong).contains(1L, 2L, 3L); + } + } @Test void readArrayEmpty() { @@ -54,7 +89,6 @@ void readArrayMultipleNumber() { } - @Test void readArrayMultipleString() { try (JsonReader reader = adapter.reader("[\"zz\",\"xx\",\"yy\"]")) { diff --git a/jsonb/src/test/java/io/avaje/jsonb/stream/DieselAdapterTest.java b/json-core/src/test/java/io/avaje/json/stream/core/DieselAdapterTest.java similarity index 91% rename from jsonb/src/test/java/io/avaje/jsonb/stream/DieselAdapterTest.java rename to json-core/src/test/java/io/avaje/json/stream/core/DieselAdapterTest.java index bca083e6..7533c5ed 100644 --- a/jsonb/src/test/java/io/avaje/jsonb/stream/DieselAdapterTest.java +++ b/json-core/src/test/java/io/avaje/json/stream/core/DieselAdapterTest.java @@ -1,8 +1,8 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.spi.BufferedJsonWriter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.stream.*; import org.junit.jupiter.api.Test; import java.io.ByteArrayOutputStream; @@ -13,7 +13,7 @@ class DieselAdapterTest { - final JsonStream adapter = JsonStream.builder().serializeNulls(true).serializeEmpty(true).failOnUnknown(false).build(); + final JsonStream adapter = CoreJsonStream.builder().serializeNulls(true).serializeEmpty(true).failOnUnknown(false).build(); @Test void readArray() { diff --git a/jsonb/src/test/java/io/avaje/jsonb/stream/EscapeTest.java b/json-core/src/test/java/io/avaje/json/stream/core/EscapeTest.java similarity index 96% rename from jsonb/src/test/java/io/avaje/jsonb/stream/EscapeTest.java rename to json-core/src/test/java/io/avaje/json/stream/core/EscapeTest.java index 856ddcd8..8ec9a0d0 100644 --- a/jsonb/src/test/java/io/avaje/jsonb/stream/EscapeTest.java +++ b/json-core/src/test/java/io/avaje/json/stream/core/EscapeTest.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import org.junit.jupiter.api.Test; diff --git a/jsonb/src/test/java/io/avaje/jsonb/stream/JParserTest.java b/json-core/src/test/java/io/avaje/json/stream/core/JParserTest.java similarity index 99% rename from jsonb/src/test/java/io/avaje/jsonb/stream/JParserTest.java rename to json-core/src/test/java/io/avaje/json/stream/core/JParserTest.java index 6e767b85..f9b58c99 100644 --- a/jsonb/src/test/java/io/avaje/jsonb/stream/JParserTest.java +++ b/json-core/src/test/java/io/avaje/json/stream/core/JParserTest.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import org.junit.jupiter.api.Test; diff --git a/jsonb/src/test/java/io/avaje/jsonb/stream/JsonNamesTest.java b/json-core/src/test/java/io/avaje/json/stream/core/JsonNamesTest.java similarity index 96% rename from jsonb/src/test/java/io/avaje/jsonb/stream/JsonNamesTest.java rename to json-core/src/test/java/io/avaje/json/stream/core/JsonNamesTest.java index ecee7d4d..5efeae98 100644 --- a/jsonb/src/test/java/io/avaje/jsonb/stream/JsonNamesTest.java +++ b/json-core/src/test/java/io/avaje/json/stream/core/JsonNamesTest.java @@ -1,4 +1,4 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import org.junit.jupiter.api.Test; diff --git a/jsonb/src/test/java/io/avaje/jsonb/stream/JsonReadAdapterTest.java b/json-core/src/test/java/io/avaje/json/stream/core/JsonReadAdapterTest.java similarity index 87% rename from jsonb/src/test/java/io/avaje/jsonb/stream/JsonReadAdapterTest.java rename to json-core/src/test/java/io/avaje/json/stream/core/JsonReadAdapterTest.java index bcea57c1..449c8ca1 100644 --- a/jsonb/src/test/java/io/avaje/jsonb/stream/JsonReadAdapterTest.java +++ b/json-core/src/test/java/io/avaje/json/stream/core/JsonReadAdapterTest.java @@ -1,7 +1,8 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.stream.Recyclers.ThreadLocalPool; +import io.avaje.json.JsonReader; +import io.avaje.json.stream.JsonStream; +import io.avaje.json.stream.core.Recyclers.ThreadLocalPool; import org.junit.jupiter.api.Test; @@ -9,8 +10,7 @@ import java.math.BigInteger; import java.nio.charset.StandardCharsets; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; class JsonReadAdapterTest { @@ -26,14 +26,14 @@ void via_jreader() { jr.process(bytes, bytes.length); JsonReadAdapter reader = - new JsonReadAdapter(jr, ThreadLocalPool.shared(), true); + new JsonReadAdapter(jr, ThreadLocalPool.shared(), true); readExampleWithAsserts(reader); reader.close(); } @Test void via_adapter_usingReader() { - JsonStream adapter = new JsonStream(false, false, false); + JsonStream adapter = JsonStream.builder().build(); try (JsonReader reader = adapter.reader(new StringReader(jsonStringInput))) { readExampleWithAsserts(reader); } @@ -44,7 +44,7 @@ void via_adapter_usingReader() { @Test void via_adapter_usingString() { - JsonStream adapter = new JsonStream(false, false, false); + JsonStream adapter = JsonStream.builder().build(); try (JsonReader reader = adapter.reader(jsonStringInput)) { readExampleWithAsserts(reader); } diff --git a/jsonb/src/test/java/io/avaje/jsonb/stream/JsonWriterTest.java b/json-core/src/test/java/io/avaje/json/stream/core/JsonWriterTest.java similarity index 89% rename from jsonb/src/test/java/io/avaje/jsonb/stream/JsonWriterTest.java rename to json-core/src/test/java/io/avaje/json/stream/core/JsonWriterTest.java index 56747f91..09140a51 100644 --- a/jsonb/src/test/java/io/avaje/jsonb/stream/JsonWriterTest.java +++ b/json-core/src/test/java/io/avaje/json/stream/core/JsonWriterTest.java @@ -1,21 +1,23 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; +import io.avaje.json.stream.JsonOutput; +import io.avaje.json.stream.JsonStream; import org.junit.jupiter.api.Test; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.stream.HybridBufferRecycler.StripedLockFreePool; -import io.avaje.jsonb.stream.Recyclers.ThreadLocalPool; +import io.avaje.json.JsonWriter; +import io.avaje.json.stream.core.HybridBufferRecycler.StripedLockFreePool; +import io.avaje.json.stream.core.Recyclers.ThreadLocalPool; class JsonWriterTest { @Test void flush_expect_flushUnderlyingWriter() { - JsonStream build = JsonStream.builder().serializeNulls(true).build(); + JsonStream build = CoreJsonStream.builder().serializeNulls(true).build(); CharArrayWriter writer = new CharArrayWriter(); JsonWriter jsonWriter = build.writer(writer); @@ -112,7 +114,7 @@ void using_names() { JsonWriteAdapter fw = new JsonWriteAdapter(dJsonWriter, HybridBufferRecycler.shared(), true, true); - JsonNames names = JsonNames.of("one", "size", "active","flags"); + JsonNames names = JsonNames.of("one", "size", "active", "flags"); fw.beginArray(); diff --git a/jsonb/src/test/java/io/avaje/jsonb/stream/StreamTest.java b/json-core/src/test/java/io/avaje/json/stream/core/StreamTest.java similarity index 93% rename from jsonb/src/test/java/io/avaje/jsonb/stream/StreamTest.java rename to json-core/src/test/java/io/avaje/json/stream/core/StreamTest.java index 290b0687..b0c949c8 100644 --- a/jsonb/src/test/java/io/avaje/jsonb/stream/StreamTest.java +++ b/json-core/src/test/java/io/avaje/json/stream/core/StreamTest.java @@ -1,6 +1,7 @@ -package io.avaje.jsonb.stream; +package io.avaje.json.stream.core; -import io.avaje.jsonb.JsonReader; +import io.avaje.json.JsonReader; +import io.avaje.json.stream.JsonStream; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; diff --git a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/ClassReader.java b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/ClassReader.java index f9591390..9a093ef7 100644 --- a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/ClassReader.java +++ b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/ClassReader.java @@ -180,18 +180,18 @@ private Set importTypes() { if (implementation != null) { implementation.addImported(importTypes); } - if (supportsViewBuilder()) { - importTypes.add("io.avaje.jsonb.spi.ViewBuilder"); - importTypes.add("io.avaje.jsonb.spi.ViewBuilderAware"); - } - importTypes.add("io.avaje.jsonb.JsonAdapter"); + importTypes.add("io.avaje.json.view.ViewBuilder"); + importTypes.add("io.avaje.json.view.ViewBuilderAware"); + } + importTypes.add("io.avaje.json.JsonAdapter"); + importTypes.add("io.avaje.json.PropertyNames"); + importTypes.add("io.avaje.json.JsonReader"); + importTypes.add("io.avaje.json.JsonWriter"); + importTypes.add("io.avaje.jsonb.AdapterFactory"); importTypes.add(Constants.JSONB); - importTypes.add("io.avaje.jsonb.JsonReader"); - importTypes.add("io.avaje.jsonb.JsonWriter"); importTypes.add("io.avaje.jsonb.Types"); importTypes.add("io.avaje.jsonb.spi.Generated"); - importTypes.add("io.avaje.jsonb.spi.PropertyNames"); return importTypes; } @@ -340,6 +340,7 @@ public void writeViewSupport(Append writer) { private void writeView(Append writer) { writer.eol(); + writer.append(" @SuppressWarnings(\"unchecked\")").eol(); writer.append(" @Override").eol(); writer.append(" public boolean isViewBuilderAware() {").eol(); writer.append(" return true;").eol(); diff --git a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/JsonbProcessor.java b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/JsonbProcessor.java index 7fb80ad6..f4f1edb5 100644 --- a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/JsonbProcessor.java +++ b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/JsonbProcessor.java @@ -120,7 +120,7 @@ private void registerCustomAdapters(Set elements) { .findFirst() .ifPresentOrElse( x -> {}, - () -> logError(typeElement, "Generic adapters require a public static JsonAdapter.Factory FACTORY field")); + () -> logError(typeElement, "Generic adapters require a public static AdapterFactory FACTORY field")); metaData.addFactory(type); } else { diff --git a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/SimpleAdapterWriter.java b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/SimpleAdapterWriter.java index 73b4fcac..a60cc82b 100644 --- a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/SimpleAdapterWriter.java +++ b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/SimpleAdapterWriter.java @@ -59,7 +59,7 @@ private void writeFactory() { if (nestedIndex != -1) { typeName = typeName.substring(nestedIndex + 1); } - writer.append(" public static final JsonAdapter.Factory FACTORY = (type, jsonb) -> {").eol(); + writer.append(" public static final AdapterFactory FACTORY = (type, jsonb) -> {").eol(); writer.append(" if (Types.isGenericTypeOf(type, %s.class)) {", typeName).eol(); writer.append(" Type[] args = Types.typeArguments(type);").eol(); writer.append(" return new %sJsonAdapter(jsonb", adapterShortName); diff --git a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/Util.java b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/Util.java index 47e25c08..70a9a858 100644 --- a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/Util.java +++ b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/Util.java @@ -182,7 +182,7 @@ static String baseTypeOfAdapter(String adapterFullName) { static String baseTypeOfAdapter(TypeElement element) { return element.getInterfaces().stream() - .filter(t -> t.toString().contains("io.avaje.jsonb.JsonAdapter")) + .filter(t -> t.toString().contains("io.avaje.json.JsonAdapter")) .findFirst() .map(Object::toString) .map(GenericType::parse) diff --git a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/ValueReader.java b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/ValueReader.java index 22c00476..d2d4b513 100644 --- a/jsonb-generator/src/main/java/io/avaje/jsonb/generator/ValueReader.java +++ b/jsonb-generator/src/main/java/io/avaje/jsonb/generator/ValueReader.java @@ -80,11 +80,11 @@ private Set importTypes() { importTypes.add(type); importTypes.add(element.asType().toString()); importTypes.add(method.getReturnType().toString()); - importTypes.add("io.avaje.jsonb.spi.PropertyNames"); - importTypes.add("io.avaje.jsonb.JsonAdapter"); - importTypes.add("io.avaje.jsonb.JsonDataException"); - importTypes.add("io.avaje.jsonb.JsonReader"); - importTypes.add("io.avaje.jsonb.JsonWriter"); + importTypes.add("io.avaje.json.JsonDataException"); + importTypes.add("io.avaje.json.PropertyNames"); + importTypes.add("io.avaje.json.JsonReader"); + importTypes.add("io.avaje.json.JsonWriter"); + importTypes.add("io.avaje.json.JsonAdapter"); importTypes.add("io.avaje.jsonb.spi.Generated"); importTypes.add(Constants.JSONB); return importTypes; diff --git a/jsonb-generator/src/main/java/module-info.java b/jsonb-generator/src/main/java/module-info.java index 1b746d40..43545422 100644 --- a/jsonb-generator/src/main/java/module-info.java +++ b/jsonb-generator/src/main/java/module-info.java @@ -1,6 +1,7 @@ module io.avaje.jsonb.generator { requires java.compiler; + requires static io.avaje.json; requires static io.avaje.jsonb; requires static io.avaje.prism; diff --git a/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/CustomEntryJsonAdapter.java b/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/CustomEntryJsonAdapter.java index 07ec6d9f..614c6a38 100644 --- a/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/CustomEntryJsonAdapter.java +++ b/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/CustomEntryJsonAdapter.java @@ -4,22 +4,20 @@ import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Map.Entry; -import io.avaje.jsonb.CustomAdapter; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.Jsonb; -import io.avaje.jsonb.Types; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.jsonb.*; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; @CustomAdapter -public class CustomEntryJsonAdapter implements JsonAdapter> { +public class CustomEntryJsonAdapter implements JsonAdapter> { private final JsonAdapter generic1; private final JsonAdapter generic2; private final PropertyNames names; - public static final JsonAdapter.Factory FACTORY = (type, jsonb) -> { + public static final AdapterFactory FACTORY = (type, jsonb) -> { if (Types.isGenericTypeOf(type, Entry.class)) { return new CustomEntryJsonAdapter<>(jsonb, Types.typeArguments(type)); } diff --git a/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/CustomJsonAdapter.java b/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/CustomJsonAdapter.java index f28beeae..3504f4ba 100644 --- a/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/CustomJsonAdapter.java +++ b/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/CustomJsonAdapter.java @@ -1,13 +1,13 @@ package io.avaje.jsonb.generator.models.valid; import io.avaje.jsonb.CustomAdapter; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.generator.models.valid.Example3Packet.Example2Packet; @CustomAdapter -public class CustomJsonAdapter implements JsonAdapter { +public class CustomJsonAdapter implements JsonAdapter { @Override public void toJson(JsonWriter writer, Example2Packet value) {} diff --git a/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/MoneySerializer.java b/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/MoneySerializer.java index 313cd249..89f3a350 100644 --- a/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/MoneySerializer.java +++ b/jsonb-generator/src/test/java/io/avaje/jsonb/generator/models/valid/MoneySerializer.java @@ -3,13 +3,13 @@ import java.math.BigDecimal; import io.avaje.jsonb.CustomAdapter; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; @CustomAdapter(global = false) -public class MoneySerializer implements JsonAdapter { +public class MoneySerializer implements JsonAdapter { public MoneySerializer(Jsonb jsonb) {} diff --git a/jsonb-jackson/pom.xml b/jsonb-jackson/pom.xml index bb1757bd..610a5351 100644 --- a/jsonb-jackson/pom.xml +++ b/jsonb-jackson/pom.xml @@ -21,7 +21,7 @@ io.avaje avaje-jsonb - 1.10-RC1 + 2.5-SNAPSHOT diff --git a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonAdapter.java b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonAdapter.java index f9dbe5ab..c5d847d6 100644 --- a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonAdapter.java +++ b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonAdapter.java @@ -4,14 +4,14 @@ import com.fasterxml.jackson.core.StreamReadFeature; import com.fasterxml.jackson.core.io.SegmentedStringWriter; import com.fasterxml.jackson.core.util.ByteArrayBuilder; -import io.avaje.jsonb.JsonIoException; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.spi.BufferedJsonWriter; -import io.avaje.jsonb.spi.BytesJsonWriter; -import io.avaje.jsonb.spi.JsonStreamAdapter; -import io.avaje.jsonb.spi.PropertyNames; -import io.avaje.jsonb.stream.JsonOutput; +import io.avaje.json.JsonIoException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; +import io.avaje.json.stream.BufferedJsonWriter; +import io.avaje.json.stream.BytesJsonWriter; +import io.avaje.json.stream.JsonStream; +import io.avaje.json.stream.JsonOutput; import java.io.*; @@ -53,7 +53,7 @@ *
  • failOnUnknown false
  • * */ -public class JacksonAdapter implements JsonStreamAdapter { +public class JacksonAdapter implements JsonStream { /** * Used to build JacksonAdapter with custom settings. diff --git a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonAdapterFactory.java b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonAdapterFactory.java index 3fc634cc..508a40d3 100644 --- a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonAdapterFactory.java +++ b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonAdapterFactory.java @@ -1,17 +1,17 @@ package io.avaje.jsonb.jackson; -import io.avaje.jsonb.spi.JsonStreamAdapter; -import io.avaje.jsonb.spi.AdapterFactory; +import io.avaje.json.stream.JsonStream; +import io.avaje.jsonb.spi.JsonStreamFactory; /** * Jackson Core based adapter. *

    * Uses jackson code to do the underlying json parsing and generation. */ -public class JacksonAdapterFactory implements AdapterFactory { +public class JacksonAdapterFactory implements JsonStreamFactory { @Override - public JsonStreamAdapter create(boolean serializeNulls, boolean serializeEmpty, boolean failOnUnknown) { + public JsonStream create(boolean serializeNulls, boolean serializeEmpty, boolean failOnUnknown) { return new JacksonAdapter(serializeNulls, serializeEmpty, failOnUnknown); } } diff --git a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonNames.java b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonNames.java index 129a958d..a4b71476 100644 --- a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonNames.java +++ b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonNames.java @@ -1,7 +1,7 @@ package io.avaje.jsonb.jackson; import com.fasterxml.jackson.core.io.SerializedString; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.json.PropertyNames; final class JacksonNames implements PropertyNames { diff --git a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonReader.java b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonReader.java index 1a62ecac..ea527a0d 100644 --- a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonReader.java +++ b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonReader.java @@ -3,9 +3,9 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.TreeNode; -import io.avaje.jsonb.JsonIoException; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.json.JsonIoException; +import io.avaje.json.JsonReader; +import io.avaje.json.PropertyNames; import java.io.IOException; import java.math.BigDecimal; diff --git a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriteAsBytes.java b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriteAsBytes.java index 1dbb2fa0..c4e70f2d 100644 --- a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriteAsBytes.java +++ b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriteAsBytes.java @@ -1,9 +1,9 @@ package io.avaje.jsonb.jackson; import com.fasterxml.jackson.core.util.ByteArrayBuilder; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.spi.BytesJsonWriter; -import io.avaje.jsonb.spi.DelegateJsonWriter; +import io.avaje.json.JsonWriter; +import io.avaje.json.stream.BytesJsonWriter; +import io.avaje.json.stream.DelegateJsonWriter; final class JacksonWriteAsBytes extends DelegateJsonWriter implements BytesJsonWriter { diff --git a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriteBuffer.java b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriteBuffer.java index 073bc318..ba250251 100644 --- a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriteBuffer.java +++ b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriteBuffer.java @@ -4,10 +4,10 @@ import com.fasterxml.jackson.core.io.SegmentedStringWriter; -import io.avaje.jsonb.JsonException; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.spi.BufferedJsonWriter; -import io.avaje.jsonb.spi.DelegateJsonWriter; +import io.avaje.json.JsonException; +import io.avaje.json.JsonWriter; +import io.avaje.json.stream.BufferedJsonWriter; +import io.avaje.json.stream.DelegateJsonWriter; final class JacksonWriteBuffer extends DelegateJsonWriter implements BufferedJsonWriter { diff --git a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriter.java b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriter.java index 3767e551..2b326f0d 100644 --- a/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriter.java +++ b/jsonb-jackson/src/main/java/io/avaje/jsonb/jackson/JacksonWriter.java @@ -1,9 +1,9 @@ package io.avaje.jsonb.jackson; import com.fasterxml.jackson.core.JsonGenerator; -import io.avaje.jsonb.JsonIoException; -import io.avaje.jsonb.JsonWriter; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.json.JsonIoException; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; import java.io.IOException; import java.math.BigDecimal; diff --git a/jsonb-jackson/src/main/java/module-info.java b/jsonb-jackson/src/main/java/module-info.java index 919433e4..9575e2f1 100644 --- a/jsonb-jackson/src/main/java/module-info.java +++ b/jsonb-jackson/src/main/java/module-info.java @@ -1,4 +1,3 @@ - module io.avaje.jsonb.jackson { requires transitive io.avaje.jsonb; @@ -6,5 +5,5 @@ exports io.avaje.jsonb.jackson; - provides io.avaje.jsonb.spi.AdapterFactory with io.avaje.jsonb.jackson.JacksonAdapterFactory; + provides io.avaje.jsonb.spi.JsonStreamFactory with io.avaje.jsonb.jackson.JacksonAdapterFactory; } diff --git a/jsonb-jackson/src/main/resources/META-INF/services/io.avaje.jsonb.spi.AdapterFactory b/jsonb-jackson/src/main/resources/META-INF/services/io.avaje.jsonb.spi.JsonStreamFactory similarity index 100% rename from jsonb-jackson/src/main/resources/META-INF/services/io.avaje.jsonb.spi.AdapterFactory rename to jsonb-jackson/src/main/resources/META-INF/services/io.avaje.jsonb.spi.JsonStreamFactory diff --git a/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/ObjectAdapterTest.java b/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/ObjectAdapterTest.java index b092b6f9..d1a531f9 100644 --- a/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/ObjectAdapterTest.java +++ b/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/ObjectAdapterTest.java @@ -1,8 +1,8 @@ package io.avaje.jsonb.jackson; -import io.avaje.jsonb.JsonAdapter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.JsonType; -import io.avaje.jsonb.JsonWriter; import io.avaje.jsonb.Jsonb; import org.junit.jupiter.api.Test; @@ -15,7 +15,7 @@ class ObjectAdapterTest { - Jsonb jsonb = Jsonb.builder().build(); + Jsonb jsonb = Jsonb.builder().adapter(new JacksonAdapter()).build(); JsonAdapter objectAdapter = jsonb.adapter(Object.class); @@ -29,7 +29,7 @@ void fromJson_readingMap() throws IOException { assertThat(value).isInstanceOf(Map.class); Map asMap = (Map) value; - assertThat(asMap.get("id")).isEqualTo(42D); + assertThat(asMap.get("id")).isEqualTo(42L); assertThat(asMap.get("name")).isEqualTo("rob"); Object fromJsonViaType = objectType.fromJson("{\"id\":42,\"name\":\"rob\"}"); @@ -46,7 +46,7 @@ void fromJson_readingListOfMap() throws IOException { List> asListOfMap = (List>) value; assertThat(asListOfMap).hasSize(2); - assertThat(asListOfMap.get(0).get("id")).isEqualTo(42D); + assertThat(asListOfMap.get(0).get("id")).isEqualTo(42L); assertThat(asListOfMap.get(0).get("name")).isEqualTo("rob"); StringWriter sw = new StringWriter(); @@ -55,11 +55,11 @@ void fromJson_readingListOfMap() throws IOException { jsonWriter.close(); String asJson = sw.toString(); - assertThat(asJson).isEqualTo("[{\"id\":42.0,\"name\":\"rob\"},{\"id\":43.0,\"name\":\"bob\"}]"); + assertThat(asJson).isEqualTo("[{\"id\":42,\"name\":\"rob\"},{\"id\":43,\"name\":\"bob\"}]"); // a bit easier using JsonType compared to JsonAdapter String asJson2 = objectType.toJson(value); - assertThat(asJson2).isEqualTo("[{\"id\":42.0,\"name\":\"rob\"},{\"id\":43.0,\"name\":\"bob\"}]"); + assertThat(asJson2).isEqualTo("[{\"id\":42,\"name\":\"rob\"},{\"id\":43,\"name\":\"bob\"}]"); } } diff --git a/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/UnwrapJacksonGeneratorTest.java b/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/UnwrapJacksonGeneratorTest.java index 48f762f1..5111cdbe 100644 --- a/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/UnwrapJacksonGeneratorTest.java +++ b/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/UnwrapJacksonGeneratorTest.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.core.io.SerializedString; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; import org.example.Address; import org.example.MyComponent; diff --git a/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/UnwrapJacksonParserTest.java b/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/UnwrapJacksonParserTest.java index ea1776ad..2ce2e065 100644 --- a/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/UnwrapJacksonParserTest.java +++ b/jsonb-jackson/src/test/java/io/avaje/jsonb/jackson/UnwrapJacksonParserTest.java @@ -3,9 +3,8 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.StreamReadFeature; -import io.avaje.jsonb.JsonReader; +import io.avaje.json.JsonReader; import io.avaje.jsonb.JsonType; import io.avaje.jsonb.Jsonb; import org.junit.jupiter.api.Test; @@ -34,7 +33,7 @@ void unwrap() { JsonType> jsonMap = jsonb.type(Object.class).map(); Map map = jsonMap.fromJson(reader); - assertThat(map.get("id")).isEqualTo(42D); + assertThat(map.get("id")).isEqualTo(42L); assertThat(map.get("name")).isEqualTo("rob"); } } diff --git a/jsonb-jackson/src/test/java/org/example/AddressJsonAdapter.java b/jsonb-jackson/src/test/java/org/example/AddressJsonAdapter.java index 1c7ae058..750f0540 100644 --- a/jsonb-jackson/src/test/java/org/example/AddressJsonAdapter.java +++ b/jsonb-jackson/src/test/java/org/example/AddressJsonAdapter.java @@ -1,16 +1,16 @@ package org.example; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; import io.avaje.jsonb.Jsonb; -import io.avaje.jsonb.spi.PropertyNames; -import io.avaje.jsonb.spi.ViewBuilder; -import io.avaje.jsonb.spi.ViewBuilderAware; +import io.avaje.json.view.ViewBuilder; +import io.avaje.json.view.ViewBuilderAware; import java.lang.invoke.MethodHandle; -public class AddressJsonAdapter implements JsonAdapter
    , ViewBuilderAware { +public class AddressJsonAdapter implements ViewBuilderAware, JsonAdapter
    { private final JsonAdapter stringAdapter; private final PropertyNames names; diff --git a/jsonb-jackson/src/test/java/org/example/ContactJsonAdapter.java b/jsonb-jackson/src/test/java/org/example/ContactJsonAdapter.java index 659f2214..5da2aa4d 100644 --- a/jsonb-jackson/src/test/java/org/example/ContactJsonAdapter.java +++ b/jsonb-jackson/src/test/java/org/example/ContactJsonAdapter.java @@ -1,15 +1,15 @@ package org.example; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; -import io.avaje.jsonb.spi.ViewBuilder; -import io.avaje.jsonb.spi.ViewBuilderAware; +import io.avaje.json.view.ViewBuilder; +import io.avaje.json.view.ViewBuilderAware; import java.lang.invoke.MethodHandle; -public class ContactJsonAdapter implements JsonAdapter, ViewBuilderAware { +public class ContactJsonAdapter implements ViewBuilderAware, JsonAdapter { private final JsonAdapter longAdapter; private final JsonAdapter stringAdapter; diff --git a/jsonb-jackson/src/test/java/org/example/CustomerJsonAdapter.java b/jsonb-jackson/src/test/java/org/example/CustomerJsonAdapter.java index 481ad0f1..58780d6e 100644 --- a/jsonb-jackson/src/test/java/org/example/CustomerJsonAdapter.java +++ b/jsonb-jackson/src/test/java/org/example/CustomerJsonAdapter.java @@ -1,15 +1,15 @@ package org.example; import io.avaje.jsonb.*; -import io.avaje.jsonb.spi.PropertyNames; -import io.avaje.jsonb.spi.ViewBuilder; -import io.avaje.jsonb.spi.ViewBuilderAware; +import io.avaje.json.*; +import io.avaje.json.view.ViewBuilder; +import io.avaje.json.view.ViewBuilderAware; import java.lang.invoke.MethodHandle; import java.time.Instant; import java.util.List; -public class CustomerJsonAdapter implements JsonAdapter, ViewBuilderAware { +public class CustomerJsonAdapter implements ViewBuilderAware, JsonAdapter { private final JsonAdapter intAdapter; private final JsonAdapter stringAdapter; diff --git a/jsonb-jackson/src/test/java/org/example/CustomerTest.java b/jsonb-jackson/src/test/java/org/example/CustomerTest.java index b83b5c5d..b15873e3 100644 --- a/jsonb-jackson/src/test/java/org/example/CustomerTest.java +++ b/jsonb-jackson/src/test/java/org/example/CustomerTest.java @@ -1,7 +1,10 @@ package org.example; -import io.avaje.jsonb.*; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonWriter; +import io.avaje.jsonb.JsonType; +import io.avaje.jsonb.JsonView; +import io.avaje.jsonb.Jsonb; import org.junit.jupiter.api.Test; import java.io.StringWriter; diff --git a/jsonb-jackson/src/test/java/org/example/MyBasicJsonAdapter.java b/jsonb-jackson/src/test/java/org/example/MyBasicJsonAdapter.java index c50c7a53..7134ea4c 100644 --- a/jsonb-jackson/src/test/java/org/example/MyBasicJsonAdapter.java +++ b/jsonb-jackson/src/test/java/org/example/MyBasicJsonAdapter.java @@ -1,18 +1,18 @@ package org.example; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; import io.avaje.jsonb.spi.Generated; -import io.avaje.jsonb.spi.PropertyNames; -import io.avaje.jsonb.spi.ViewBuilder; -import io.avaje.jsonb.spi.ViewBuilderAware; +import io.avaje.json.PropertyNames; +import io.avaje.json.view.ViewBuilder; +import io.avaje.json.view.ViewBuilderAware; import java.lang.invoke.MethodHandle; @Generated -public final class MyBasicJsonAdapter implements JsonAdapter, ViewBuilderAware { +public final class MyBasicJsonAdapter implements ViewBuilderAware, JsonAdapter { // naming convention Match // id [int] name:id constructor diff --git a/jsonb-jackson/src/test/java/org/example/MyComponent.java b/jsonb-jackson/src/test/java/org/example/MyComponent.java index ad90a813..825c8ff7 100644 --- a/jsonb-jackson/src/test/java/org/example/MyComponent.java +++ b/jsonb-jackson/src/test/java/org/example/MyComponent.java @@ -1,12 +1,13 @@ package org.example; import io.avaje.jsonb.Jsonb; +import io.avaje.jsonb.spi.GeneratedComponent; import io.avaje.jsonb.spi.Generated; import io.avaje.jsonb.spi.MetaData; @Generated @MetaData({CustomerJsonAdapter.class, ContactJsonAdapter.class}) -public class MyComponent implements Jsonb.GeneratedComponent { +public class MyComponent implements GeneratedComponent { @Override public void register(Jsonb.Builder builder) { diff --git a/jsonb-jackson/src/test/java/org/example/MyEnumJsonAdapter.java b/jsonb-jackson/src/test/java/org/example/MyEnumJsonAdapter.java index c0bd1150..b832ed79 100644 --- a/jsonb-jackson/src/test/java/org/example/MyEnumJsonAdapter.java +++ b/jsonb-jackson/src/test/java/org/example/MyEnumJsonAdapter.java @@ -4,10 +4,10 @@ import java.util.HashMap; import java.util.Map; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonDataException; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonDataException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; import io.avaje.jsonb.spi.Generated; diff --git a/jsonb-jackson/src/test/java/org/example/MyIntEnumJsonAdapter.java b/jsonb-jackson/src/test/java/org/example/MyIntEnumJsonAdapter.java index 368a1b6f..e747dd24 100644 --- a/jsonb-jackson/src/test/java/org/example/MyIntEnumJsonAdapter.java +++ b/jsonb-jackson/src/test/java/org/example/MyIntEnumJsonAdapter.java @@ -4,10 +4,10 @@ import java.util.HashMap; import java.util.Map; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonDataException; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonDataException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; public final class MyIntEnumJsonAdapter implements JsonAdapter { diff --git a/jsonb-jackson/src/test/java/org/example/StreamBasicTest.java b/jsonb-jackson/src/test/java/org/example/StreamBasicTest.java index b9e80135..2ad88139 100644 --- a/jsonb-jackson/src/test/java/org/example/StreamBasicTest.java +++ b/jsonb-jackson/src/test/java/org/example/StreamBasicTest.java @@ -1,7 +1,7 @@ package org.example; import io.avaje.jsonb.Json; -import io.avaje.jsonb.JsonReader; +import io.avaje.json.JsonReader; import io.avaje.jsonb.JsonType; import io.avaje.jsonb.Jsonb; import org.junit.jupiter.api.Test; diff --git a/jsonb/pom.xml b/jsonb/pom.xml index 96342239..894583df 100644 --- a/jsonb/pom.xml +++ b/jsonb/pom.xml @@ -13,20 +13,18 @@ + + io.avaje + avaje-json + ${project.version} + + io.avaje avaje-jsonb-inject-plugin ${project.version} - - io.helidon.webserver - helidon-webserver - 4.1.0 - provided - true - - io.avaje avaje-spi-service diff --git a/jsonb/src/main/java/io/avaje/jsonb/AdapterFactory.java b/jsonb/src/main/java/io/avaje/jsonb/AdapterFactory.java new file mode 100644 index 00000000..04f96cbd --- /dev/null +++ b/jsonb/src/main/java/io/avaje/jsonb/AdapterFactory.java @@ -0,0 +1,17 @@ +package io.avaje.jsonb; + +import java.lang.reflect.Type; +import io.avaje.json.JsonAdapter; + +/** + * Factory for creating a JsonAdapter. + */ +public interface AdapterFactory { + + /** + * Create and return a JsonAdapter given the type and annotations or return null. + *

    + * Returning null means that the adapter could be created by another factory. + */ + JsonAdapter create(Type type, Jsonb jsonb); +} diff --git a/jsonb/src/main/java/io/avaje/jsonb/Json.java b/jsonb/src/main/java/io/avaje/jsonb/Json.java index 78b571ff..a44a4ed6 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/Json.java +++ b/jsonb/src/main/java/io/avaje/jsonb/Json.java @@ -13,6 +13,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; +import io.avaje.json.JsonAdapter; import io.avaje.jsonb.Json.Import.Imports; /** diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonType.java b/jsonb/src/main/java/io/avaje/jsonb/JsonType.java index 098455f3..131b5531 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonType.java +++ b/jsonb/src/main/java/io/avaje/jsonb/JsonType.java @@ -1,5 +1,7 @@ package io.avaje.jsonb; +import io.avaje.json.JsonReader; + import java.io.InputStream; import java.io.Reader; import java.util.List; diff --git a/jsonb/src/main/java/io/avaje/jsonb/JsonView.java b/jsonb/src/main/java/io/avaje/jsonb/JsonView.java index 49a245e0..bbe91020 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/JsonView.java +++ b/jsonb/src/main/java/io/avaje/jsonb/JsonView.java @@ -1,6 +1,7 @@ package io.avaje.jsonb; -import io.avaje.jsonb.stream.JsonOutput; +import io.avaje.json.stream.JsonOutput; +import io.avaje.json.JsonWriter; import java.io.OutputStream; import java.io.Writer; diff --git a/jsonb/src/main/java/io/avaje/jsonb/Jsonb.java b/jsonb/src/main/java/io/avaje/jsonb/Jsonb.java index 56546f45..19331751 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/Jsonb.java +++ b/jsonb/src/main/java/io/avaje/jsonb/Jsonb.java @@ -1,12 +1,13 @@ package io.avaje.jsonb; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; +import io.avaje.json.stream.*; import io.avaje.jsonb.core.DefaultBootstrap; -import io.avaje.jsonb.spi.AdapterFactory; -import io.avaje.jsonb.spi.JsonStreamAdapter; +import io.avaje.jsonb.spi.JsonStreamFactory; import io.avaje.jsonb.spi.JsonbComponent; -import io.avaje.jsonb.spi.PropertyNames; -import io.avaje.jsonb.stream.BufferRecycleStrategy; -import io.avaje.jsonb.stream.JsonOutput; import java.io.InputStream; import java.io.OutputStream; @@ -386,12 +387,12 @@ interface Builder { /** * Explicitly set the adapter to use. *

    - * When not set the JsonStreamAdapter is service loaded using {@link AdapterFactory} + * When not set the JsonStreamAdapter is service loaded using {@link JsonStreamFactory} * with a fallback default of using the built-in implementation. * * @param streamAdapter The underlying adapter to use when generating and parsing */ - Builder adapter(JsonStreamAdapter streamAdapter); + Builder adapter(JsonStream streamAdapter); /** * Add a JsonAdapter to use for the given type. @@ -416,7 +417,7 @@ interface Builder { /** * Add a JsonAdapter.Factory which provides JsonAdapters to use. */ - Builder add(JsonAdapter.Factory factory); + Builder add(AdapterFactory factory); /** * Build and return the Jsonb instance with all the given adapters and factories registered. diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/BasicTypeAdapters.java b/jsonb/src/main/java/io/avaje/jsonb/core/BasicTypeAdapters.java index aa0cb11a..6681cb09 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/BasicTypeAdapters.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/BasicTypeAdapters.java @@ -15,6 +15,10 @@ */ package io.avaje.jsonb.core; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonDataException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.*; import java.lang.reflect.Type; @@ -26,25 +30,14 @@ final class BasicTypeAdapters { @SuppressWarnings({"unchecked", "rawtypes"}) - static final JsonAdapter.Factory FACTORY = + static final AdapterFactory FACTORY = (type, jsonb) -> { - if (type == Boolean.TYPE) return new BooleanAdapter(); if (type == Byte.TYPE) return new ByteAdapter(); if (type == Character.TYPE) return new CharacterAdapter(); - if (type == Double.TYPE) return new DoubleAdapter(); - if (type == Float.TYPE) return new FloatAdapter(); - if (type == Integer.TYPE) return new IntegerAdapter(); - if (type == Long.TYPE) return new LongAdapter(); if (type == Short.TYPE) return new ShortAdapter(); - if (type == Boolean.class) return new BooleanAdapter().nullSafe(); if (type == Byte.class) return new ByteAdapter().nullSafe(); if (type == Character.class) return new CharacterAdapter().nullSafe(); - if (type == Double.class) return new DoubleAdapter().nullSafe(); - if (type == Float.class) return new FloatAdapter().nullSafe(); - if (type == Integer.class) return new IntegerAdapter().nullSafe(); - if (type == Long.class) return new LongAdapter().nullSafe(); if (type == Short.class) return new ShortAdapter().nullSafe(); - if (type == String.class) return new StringAdapter().nullSafe(); if (type == UUID.class) return new UuidAdapter().nullSafe(); if (type == URL.class) return new UrlAdapter().nullSafe(); if (type == URI.class) return new UriAdapter().nullSafe(); @@ -388,7 +381,7 @@ static int rangeCheckNextInt(JsonReader reader, String typeMessage, int min, int @SuppressWarnings("rawtypes") static final class ObjectJsonAdapter implements JsonAdapter { private final Jsonb jsonb; - private final JsonAdapter listJsonAdapter; + private final JsonAdapter listAdapter; private final JsonAdapter mapAdapter; private final JsonAdapter stringAdapter; private final JsonAdapter doubleAdapter; @@ -396,7 +389,7 @@ static final class ObjectJsonAdapter implements JsonAdapter { ObjectJsonAdapter(Jsonb jsonb) { this.jsonb = jsonb; - this.listJsonAdapter = jsonb.adapter(List.class); + this.listAdapter = jsonb.adapter(List.class); this.mapAdapter = jsonb.adapter(Map.class); this.stringAdapter = jsonb.adapter(String.class); this.doubleAdapter = jsonb.adapter(Double.class); @@ -407,19 +400,19 @@ static final class ObjectJsonAdapter implements JsonAdapter { public Object fromJson(JsonReader reader) { switch (reader.currentToken()) { case BEGIN_ARRAY: - return this.listJsonAdapter.fromJson(reader); + return listAdapter.fromJson(reader); case BEGIN_OBJECT: - return this.mapAdapter.fromJson(reader); + return mapAdapter.fromJson(reader); case STRING: - return this.stringAdapter.fromJson(reader); + return stringAdapter.fromJson(reader); case NUMBER: - var d = this.doubleAdapter.fromJson(reader); + var d = doubleAdapter.fromJson(reader); if (d % 1 == 0) { return d.longValue(); } return d; case BOOLEAN: - return this.booleanAdapter.fromJson(reader); + return booleanAdapter.fromJson(reader); case NULL: return null; default: diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/CoreAdapterBuilder.java b/jsonb/src/main/java/io/avaje/jsonb/core/CoreAdapterBuilder.java index e5505649..0f4b0f36 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/CoreAdapterBuilder.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/CoreAdapterBuilder.java @@ -15,9 +15,10 @@ */ package io.avaje.jsonb.core; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.jsonb.AdapterFactory; import java.lang.reflect.Type; import java.util.*; @@ -30,22 +31,23 @@ final class CoreAdapterBuilder { private final DJsonb context; - private final List factories; + private final List factories; private final ThreadLocal lookupChainThreadLocal = new ThreadLocal<>(); private final Map> adapterCache = new ConcurrentHashMap<>(); private final ReentrantLock lock = new ReentrantLock(); - CoreAdapterBuilder(DJsonb context, List userFactories, boolean mathAsString) { + CoreAdapterBuilder(DJsonb context, List userFactories, boolean mathAsString) { this.context = context; this.factories = new ArrayList<>(); this.factories.addAll(userFactories); + this.factories.add(CoreAdapters.FACTORY); this.factories.add(BasicTypeAdapters.FACTORY); this.factories.add(JavaTimeAdapters.FACTORY); this.factories.add(new MathAdapters(mathAsString)); - this.factories.add(CollectionAdapter.FACTORY); - this.factories.add(MapAdapter.FACTORY); + this.factories.add(CoreAdapters.COLLECTION_FACTORY); + this.factories.add(CoreAdapters.MAP_FACTORY); this.factories.add(EnumMapAdapter.FACTORY); - this.factories.add(ArrayAdapter.FACTORY); + this.factories.add(CoreAdapters.ARRAY_FACTORY); this.factories.add(OptionalAdapters.FACTORY); } @@ -82,7 +84,7 @@ JsonAdapter build(Type type, Object cacheKey) { return adapterFromCall; } // Ask each factory to create the JSON adapter. - for (JsonAdapter.Factory factory : factories) { + for (AdapterFactory factory : factories) { JsonAdapter result = (JsonAdapter) factory.create(type, context); if (result != null) { // Success! Notify the LookupChain so it is cached and can be used by re-entrant calls. diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/CoreAdapters.java b/jsonb/src/main/java/io/avaje/jsonb/core/CoreAdapters.java new file mode 100644 index 00000000..a64e5f71 --- /dev/null +++ b/jsonb/src/main/java/io/avaje/jsonb/core/CoreAdapters.java @@ -0,0 +1,61 @@ +package io.avaje.jsonb.core; + +import io.avaje.json.JsonAdapter; +import io.avaje.json.core.CoreTypes; +import io.avaje.jsonb.AdapterFactory; +import io.avaje.jsonb.Jsonb; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +final class CoreAdapters { + + static final AdapterFactory FACTORY = (type, jsonb) -> CoreTypes.create(type); + + static final AdapterFactory ARRAY_FACTORY = (type, jsonb) -> { + Type elementType = Util.arrayComponentType(type); + if (elementType == null) return null; + if (elementType == byte.class) return CoreTypes.byteArray(); + Class elementClass = Util.rawType(elementType); + JsonAdapter elementAdapter = jsonb.adapter(elementType); + return CoreTypes.createArray(elementClass, elementAdapter).nullSafe(); + }; + + static final AdapterFactory MAP_FACTORY = (type, jsonb) -> { + final var rawType = Util.rawType(type); + if (rawType != Map.class) { + return null; + } + final var valueTypes = Util.mapValueTypes(type, rawType); + if (valueTypes[0] != String.class) { + return null; + } + JsonAdapter valueAdapter = jsonb.adapter(valueTypes[1]); + return CoreTypes.createMap(valueAdapter); + }; + + static final AdapterFactory COLLECTION_FACTORY = (type, jsonb) -> { + Class rawType = Util.rawType(type); + if (rawType == List.class || rawType == Collection.class) { + return newListAdapter(type, jsonb).nullSafe(); + } else if (rawType == Set.class) { + return newSetAdapter(type, jsonb).nullSafe(); + } + return null; + }; + + private static JsonAdapter> newListAdapter(Type type, Jsonb jsonb) { + Type elementType = Util.collectionElementType(type); + JsonAdapter elementAdapter = jsonb.adapter(elementType); + return CoreTypes.createList(elementAdapter); + } + + private static JsonAdapter> newSetAdapter(Type type, Jsonb jsonb) { + Type elementType = Util.collectionElementType(type); + JsonAdapter elementAdapter = jsonb.adapter(elementType); + return CoreTypes.createSet(elementAdapter); + } +} diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/CoreViewBuilder.java b/jsonb/src/main/java/io/avaje/jsonb/core/CoreViewBuilder.java index 726f33a4..91abe2d0 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/CoreViewBuilder.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/CoreViewBuilder.java @@ -1,11 +1,9 @@ package io.avaje.jsonb.core; +import io.avaje.json.*; import io.avaje.jsonb.*; -import io.avaje.jsonb.spi.BufferedJsonWriter; -import io.avaje.jsonb.spi.BytesJsonWriter; -import io.avaje.jsonb.spi.PropertyNames; -import io.avaje.jsonb.spi.ViewBuilder; -import io.avaje.jsonb.stream.JsonOutput; +import io.avaje.json.stream.*; +import io.avaje.json.view.ViewBuilder; import java.io.IOException; import java.io.OutputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/DJsonClosable.java b/jsonb/src/main/java/io/avaje/jsonb/core/DJsonClosable.java index a110c905..6e9ff7d6 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/DJsonClosable.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/DJsonClosable.java @@ -1,6 +1,6 @@ package io.avaje.jsonb.core; -import io.avaje.jsonb.JsonReader; +import io.avaje.json.JsonReader; /** * Adapter that supports closing the JsonReader when returned object (aka Stream) is closed. diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/DJsonStreamType.java b/jsonb/src/main/java/io/avaje/jsonb/core/DJsonStreamType.java index c00a92d4..27b70f9b 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/DJsonStreamType.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/DJsonStreamType.java @@ -1,7 +1,7 @@ package io.avaje.jsonb.core; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; import io.avaje.jsonb.JsonType; import java.io.InputStream; diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/DJsonType.java b/jsonb/src/main/java/io/avaje/jsonb/core/DJsonType.java index 37ddd834..862d4fae 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/DJsonType.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/DJsonType.java @@ -1,9 +1,11 @@ package io.avaje.jsonb.core; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.stream.*; import io.avaje.jsonb.*; -import io.avaje.jsonb.spi.BufferedJsonWriter; -import io.avaje.jsonb.spi.BytesJsonWriter; -import io.avaje.jsonb.stream.JsonOutput; import java.io.*; import java.lang.reflect.Type; @@ -54,7 +56,7 @@ public final JsonType> map() { public final JsonType> optional() { return jsonb.type(Types.optionalOf(type)); } - + @Override public final String toJson(T value) { try (BufferedJsonWriter writer = jsonb.bufferedWriter()) { diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/DJsonb.java b/jsonb/src/main/java/io/avaje/jsonb/core/DJsonb.java index 51f65931..def162cc 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/DJsonb.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/DJsonb.java @@ -1,10 +1,13 @@ package io.avaje.jsonb.core; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; +import io.avaje.json.PropertyNames; +import io.avaje.json.stream.*; import io.avaje.jsonb.*; +import io.avaje.jsonb.AdapterFactory; import io.avaje.jsonb.spi.*; -import io.avaje.jsonb.stream.BufferRecycleStrategy; -import io.avaje.jsonb.stream.JsonOutput; -import io.avaje.jsonb.stream.JsonStream; import java.io.InputStream; import java.io.OutputStream; @@ -24,14 +27,14 @@ final class DJsonb implements Jsonb { private final CoreAdapterBuilder builder; - private final JsonStreamAdapter io; + private final JsonStream io; private final Map> typeCache = new ConcurrentHashMap<>(); private final ConcurrentHashMap> viewCache = new ConcurrentHashMap<>(); private final JsonType anyType; DJsonb( - JsonStreamAdapter adapter, - List factories, + JsonStream adapter, + List factories, boolean serializeNulls, boolean serializeEmpty, boolean failOnUnknown, @@ -46,7 +49,12 @@ final class DJsonb implements Jsonb { if (adapterFactoryOptional.isPresent()) { this.io = adapterFactoryOptional.get().create(serializeNulls, serializeEmpty, failOnUnknown); } else { - this.io = new JsonStream(serializeNulls, serializeEmpty, failOnUnknown, strategy); + this.io = JsonStream.builder() + .serializeNulls(serializeNulls) + .serializeEmpty(serializeEmpty) + .failOnUnknown(failOnUnknown) + .bufferRecycling(strategy) + .build(); } } this.anyType = type(Object.class); @@ -229,12 +237,12 @@ public int hashCode() { */ static final class DBuilder implements Jsonb.Builder { - private final List factories = new ArrayList<>(); + private final List factories = new ArrayList<>(); private boolean failOnUnknown; private boolean mathTypesAsString; private boolean serializeNulls; private boolean serializeEmpty = true; - private JsonStreamAdapter adapter; + private JsonStream adapter; private BufferRecycleStrategy strategy = BufferRecycleStrategy.HYBRID_POOL; @Override @@ -268,7 +276,7 @@ public Builder bufferRecycling(BufferRecycleStrategy strategy) { } @Override - public Builder adapter(JsonStreamAdapter streamAdapter) { + public Builder adapter(JsonStream streamAdapter) { this.adapter = streamAdapter; return this; } @@ -295,7 +303,7 @@ public Builder add(JsonbComponent component) { } @Override - public Builder add(JsonAdapter.Factory factory) { + public Builder add(AdapterFactory factory) { factories.add(factory); return this; } @@ -316,19 +324,19 @@ public DJsonb build() { return new DJsonb(adapter, factories, serializeNulls, serializeEmpty, failOnUnknown, mathTypesAsString, strategy); } - static JsonAdapter.Factory newAdapterFactory(Type type, JsonAdapter jsonAdapter) { + static AdapterFactory newAdapterFactory(Type type, JsonAdapter jsonAdapter) { requireNonNull(type); requireNonNull(jsonAdapter); return (targetType, jsonb) -> simpleMatch(type, targetType) ? jsonAdapter : null; } - static JsonAdapter.Factory newAdapterFactory(Type type, Supplier> jsonAdapter) { + static AdapterFactory newAdapterFactory(Type type, Supplier> jsonAdapter) { requireNonNull(type); requireNonNull(jsonAdapter); return (targetType, jsonb) -> simpleMatch(type, targetType) ? jsonAdapter.get() : null; } - static JsonAdapter.Factory newAdapterFactory(Type type, AdapterBuilder builder) { + static AdapterFactory newAdapterFactory(Type type, AdapterBuilder builder) { requireNonNull(type); requireNonNull(builder); return (targetType, jsonb) -> simpleMatch(type, targetType) ? builder.build(jsonb).nullSafe() : null; diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/EnumMapAdapter.java b/jsonb/src/main/java/io/avaje/jsonb/core/EnumMapAdapter.java index 8cbfb534..61cd16d0 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/EnumMapAdapter.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/EnumMapAdapter.java @@ -1,5 +1,9 @@ package io.avaje.jsonb.core; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonDataException; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.*; import java.lang.reflect.Type; @@ -10,7 +14,7 @@ @SuppressWarnings("unchecked") final class EnumMapAdapter, V> implements JsonAdapter> { - static final Factory FACTORY = + static final AdapterFactory FACTORY = (type, jsonb) -> { final var rawType = Util.rawType(type); if (rawType != EnumMap.class && rawType != Map.class) { diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/ExtensionLoader.java b/jsonb/src/main/java/io/avaje/jsonb/core/ExtensionLoader.java index 1d4dcd83..bcbedc32 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/ExtensionLoader.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/ExtensionLoader.java @@ -5,7 +5,7 @@ import java.util.Optional; import java.util.ServiceLoader; -import io.avaje.jsonb.spi.AdapterFactory; +import io.avaje.jsonb.spi.JsonStreamFactory; import io.avaje.jsonb.spi.GeneratedComponent; import io.avaje.jsonb.spi.JsonbComponent; import io.avaje.jsonb.spi.JsonbExtension; @@ -15,7 +15,7 @@ final class ExtensionLoader { private static final List generatedComponents = new ArrayList<>(); private static final List userComponents = new ArrayList<>(); - private static Optional adapterFactory = Optional.empty(); + private static Optional adapterFactory = Optional.empty(); static { for (var spi : ServiceLoader.load(JsonbExtension.class)) { @@ -23,8 +23,8 @@ final class ExtensionLoader { generatedComponents.add((GeneratedComponent) spi); } else if (spi instanceof JsonbComponent) { userComponents.add((JsonbComponent) spi); - } else if (spi instanceof AdapterFactory) { - adapterFactory = Optional.of((AdapterFactory) spi); + } else if (spi instanceof JsonStreamFactory) { + adapterFactory = Optional.of((JsonStreamFactory) spi); } } } @@ -37,7 +37,7 @@ static List userComponents() { return userComponents; } - static Optional adapterFactory() { + static Optional adapterFactory() { return adapterFactory; } } diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/JavaTimeAdapters.java b/jsonb/src/main/java/io/avaje/jsonb/core/JavaTimeAdapters.java index c6a9a0ae..3496aae4 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/JavaTimeAdapters.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/JavaTimeAdapters.java @@ -2,9 +2,10 @@ import java.util.Date; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.jsonb.AdapterFactory; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import java.time.*; @@ -13,7 +14,7 @@ */ final class JavaTimeAdapters { - static final JsonAdapter.Factory FACTORY = (type, jsonb) -> { + static final AdapterFactory FACTORY = (type, jsonb) -> { if (type == Instant.class) return JavaTimeAdapters.INSTANT_ADAPTER.nullSafe(); if (type == LocalDate.class) return JavaTimeAdapters.LOCAL_DATE_ADAPTER.nullSafe(); if (type == LocalDateTime.class) return JavaTimeAdapters.LOCAL_DATE_TIME_ADAPTER.nullSafe(); diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/MathAdapters.java b/jsonb/src/main/java/io/avaje/jsonb/core/MathAdapters.java index 031795ff..0f7de766 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/MathAdapters.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/MathAdapters.java @@ -1,15 +1,16 @@ package io.avaje.jsonb.core; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.jsonb.AdapterFactory; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; -final class MathAdapters implements JsonAdapter.Factory { +final class MathAdapters implements AdapterFactory { private final JsonAdapter decimal; private final JsonAdapter bigint; diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/ObjectJsonReader.java b/jsonb/src/main/java/io/avaje/jsonb/core/ObjectJsonReader.java index 16c516bb..21aab71b 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/ObjectJsonReader.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/ObjectJsonReader.java @@ -1,7 +1,7 @@ package io.avaje.jsonb.core; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.spi.PropertyNames; +import io.avaje.json.JsonReader; +import io.avaje.json.PropertyNames; import java.math.BigDecimal; import java.math.BigInteger; diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/OptionalAdapters.java b/jsonb/src/main/java/io/avaje/jsonb/core/OptionalAdapters.java index f1f998fb..e4c383aa 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/OptionalAdapters.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/OptionalAdapters.java @@ -6,18 +6,19 @@ import java.util.OptionalInt; import java.util.OptionalLong; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.view.ViewBuilderAware; +import io.avaje.jsonb.AdapterFactory; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import io.avaje.jsonb.Jsonb; import io.avaje.jsonb.Types; -import io.avaje.jsonb.spi.ViewBuilderAware; final class OptionalAdapters { private OptionalAdapters() {} - static final JsonAdapter.Factory FACTORY = (type, jsonb) -> { + static final AdapterFactory FACTORY = (type, jsonb) -> { if (Types.isGenericTypeOf(type, Optional.class)) { final Type[] args = Types.typeArguments(type); return new OptionalAdapter<>(jsonb, args[0]).nullSafe(); diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/RawAdapter.java b/jsonb/src/main/java/io/avaje/jsonb/core/RawAdapter.java index 1eec08ec..ca5c13a5 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/RawAdapter.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/RawAdapter.java @@ -1,8 +1,8 @@ package io.avaje.jsonb.core; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; final class RawAdapter { diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/StreamAdapter.java b/jsonb/src/main/java/io/avaje/jsonb/core/StreamAdapter.java index fddb9040..4f45448d 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/StreamAdapter.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/StreamAdapter.java @@ -1,8 +1,8 @@ package io.avaje.jsonb.core; -import io.avaje.jsonb.JsonAdapter; -import io.avaje.jsonb.JsonReader; -import io.avaje.jsonb.JsonWriter; +import io.avaje.json.JsonAdapter; +import io.avaje.json.JsonReader; +import io.avaje.json.JsonWriter; import java.util.Iterator; import java.util.Spliterator; @@ -11,7 +11,7 @@ import static java.util.Spliterators.spliteratorUnknownSize; import static java.util.stream.StreamSupport.stream; -final class StreamAdapter implements JsonAdapter>, DJsonClosable> { +final class StreamAdapter implements DJsonClosable>, JsonAdapter> { private final JsonAdapter elementAdapter; diff --git a/jsonb/src/main/java/io/avaje/jsonb/core/package-info.java b/jsonb/src/main/java/io/avaje/jsonb/core/package-info.java index ddc4eb01..adbed3aa 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/core/package-info.java +++ b/jsonb/src/main/java/io/avaje/jsonb/core/package-info.java @@ -1,4 +1,6 @@ /** * Core internal implementation. + * + * @see io.avaje.jsonb.core.DefaultBootstrap#builder() */ package io.avaje.jsonb.core; diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/AdapterFactory.java b/jsonb/src/main/java/io/avaje/jsonb/spi/JsonStreamFactory.java similarity index 72% rename from jsonb/src/main/java/io/avaje/jsonb/spi/AdapterFactory.java rename to jsonb/src/main/java/io/avaje/jsonb/spi/JsonStreamFactory.java index 346a7101..9e839a9b 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/AdapterFactory.java +++ b/jsonb/src/main/java/io/avaje/jsonb/spi/JsonStreamFactory.java @@ -1,9 +1,11 @@ package io.avaje.jsonb.spi; +import io.avaje.json.stream.JsonStream; + /** * Factory that is service loaded to create the adapter for underlying json parsing and generation. */ -public interface AdapterFactory extends JsonbExtension { +public interface JsonStreamFactory extends JsonbExtension { /** * Create the adapter to use for the underlying json parsing and generation. @@ -13,5 +15,5 @@ public interface AdapterFactory extends JsonbExtension { * @param failOnUnknown The default setting for fail when deserializing unknown properties * @return The adapter to use */ - JsonStreamAdapter create(boolean serializeNulls, boolean serializeEmpty, boolean failOnUnknown); + JsonStream create(boolean serializeNulls, boolean serializeEmpty, boolean failOnUnknown); } diff --git a/jsonb/src/main/java/io/avaje/jsonb/spi/JsonbExtension.java b/jsonb/src/main/java/io/avaje/jsonb/spi/JsonbExtension.java index 161f7e32..9d785639 100644 --- a/jsonb/src/main/java/io/avaje/jsonb/spi/JsonbExtension.java +++ b/jsonb/src/main/java/io/avaje/jsonb/spi/JsonbExtension.java @@ -7,7 +7,7 @@ * * @see JsonbComponent * @see GeneratedComponent - * @see AdapterFactory + * @see JsonStreamFactory */ @Service public interface JsonbExtension { diff --git a/jsonb/src/main/java/io/avaje/jsonb/stream/BufferRecycleStrategy.java b/jsonb/src/main/java/io/avaje/jsonb/stream/BufferRecycleStrategy.java deleted file mode 100644 index 9c47eb48..00000000 --- a/jsonb/src/main/java/io/avaje/jsonb/stream/BufferRecycleStrategy.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.avaje.jsonb.stream; - -import java.util.function.Supplier; - -/** Strategy for recycling buffers used in parsing and generation. */ -public enum BufferRecycleStrategy { - - /** Do not perform any sort of recycling. */ - NO_RECYCLING(BufferRecycler::nonRecyclingPool), - /** A lock free implementation designed for virtual thread use */ - LOCK_FREE(BufferRecycler::lockFreePool), - /** Use Thread Locals for recycling buffers */ - THREAD_LOCAL(BufferRecycler::threadLocalPool), - /** Use 2 recyclers and switch between them depending on the nature of thread (virtual or not) */ - HYBRID_POOL(BufferRecycler::hybrid); - - private final Supplier supplier; - - BufferRecycleStrategy(Supplier supplier) { - this.supplier = supplier; - } - - BufferRecycler recycler() { - return supplier.get(); - } -} diff --git a/jsonb/src/main/java/module-info.java b/jsonb/src/main/java/module-info.java index f88125de..e3461a3f 100644 --- a/jsonb/src/main/java/module-info.java +++ b/jsonb/src/main/java/module-info.java @@ -1,13 +1,11 @@ - module io.avaje.jsonb { exports io.avaje.jsonb; - exports io.avaje.jsonb.stream; exports io.avaje.jsonb.spi; uses io.avaje.jsonb.spi.JsonbExtension; - requires static io.helidon.webserver; + requires transitive io.avaje.json; requires static io.avaje.spi; } diff --git a/pom.xml b/pom.xml index 660199f4..bfca3019 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,7 @@ + json-core jsonb jsonb-generator jsonb-jackson